Walk Native Callstack without Symbolic Info

As being taking charge of CER project, reviewing some basic knowledge of callstack should be useful. Here is a demo code used to walk callstack when an unhandled exception is raised. In fact, the demo code of StackWalk1 should be able to walk in a common case. It’s just difficult to obtain a thread-related CONTEXT. Win32 API GetThreadContext will only work as expected when the thread being inspected is suppended.
[principle]
I think the principle is supposed to be easy enough, just using ebp register, and traverse the list that ebp represents.
[Note]
The demo code is CPU specific. I am working on an X86 duel core CPU.
The demo code should be running with out FPO (Frame Pointer Omit) optimization.
[Shortcoming]
The callstack dumped out is shown as raw linear address.
 
#include "stdafx.h"
#include "windows.h"
LPTOP_LEVEL_EXCEPTION_FILTER previousFilter;
void StackWalk1(PCONTEXT pContext);
LONG WINAPI MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo);
int _tmain(int argc, _TCHAR* argv[])
{
 previousFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
 // cause a EXCEPTION_FLT_DIVIDE_BY_ZERO
 int a = 0;
 int b = 1 / a;
 return 0;
}
LONG WINAPI MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
{
 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
 _tprintf(_T("Exception code: [%08x]\n"),
  pExceptionRecord->ExceptionCode);
 StackWalk1(pExceptionInfo->ContextRecord);
 if (previousFilter)
  return previousFilter(pExceptionInfo); // bypass to the user-installed handler
 else
  return EXCEPTION_CONTINUE_SEARCH; // transfer the control to operating system
}
//
// stack walker version 1, without symbol information
// should not be FPO optimization
//
void StackWalk1(PCONTEXT pContext)
{
 _tprintf(_T("Callstack:\n"));
 _tprintf(_T("Address     Frame     Module\n"));
 // instruction pointer (EIP) at the time of the exception
 DWORD pc = pContext->Eip;
 PDWORD pFrame, pPrevFrame;
 pFrame = (PDWORD)pContext->Ebp;
 do
 {
  TCHAR szModule[MAX_PATH] = { 0 };
  MEMORY_BASIC_INFORMATION mbi;
  VirtualQuery((PVOID)pc, &mbi, sizeof(mbi));
  GetModuleFileName((HMODULE)mbi.AllocationBase, szModule, sizeof(szModule));
  _tprintf(_T("%08x    %08x    %s\n"), pc, pFrame, szModule);
  // push ebp
  // mov ebp, esp, looking at the following snapshot of a stack
  // [0x…]return address   pContext->Ebp[1]
  // [0x…]ebp                 pContext->Ebp[0]

  pc = pFrame[1];
  pPrevFrame = pFrame;
  pFrame = (PDWORD)pFrame[0];
  // check if the ebp is still valid, otherwise stop walking
  if ((DWORD)pFrame & 3)
   break;
  if (pFrame <= pPrevFrame)
   break;
  // check if the address pointed to by ebp is committed
  if (IsBadWritePtr(pFrame, sizeof(PVOID) * 2))
   break;
 } while (1);
 // when to stop the walking?
 // when it encounters a frame address that doesn’t look valid
}
[Result/Output]
Exception code: [c0000094]
Callstack:
Address     Frame     Module
00bb1414    0016f8a0    d:\Visual Studio 2008\VectoredExceptDemo\Debug\MyStackwalker.exe
00bb25b8    0016f8f0    d:\Visual Studio 2008\VectoredExceptDemo\Debug\MyStackwalker.exe
00bb23ff    0016f8f8    d:\Visual Studio 2008\VectoredExceptDemo\Debug\MyStackwalker.exe
76d84911    0016f904    C:\Windows\system32\kernel32.dll
76e5e4b6    0016f944    C:\Windows\system32\ntdll.dll
76e5e489    0016f95c    C:\Windows\system32\ntdll.dll

Iteration

[Extract from ‘Message of the week’ by Wesley Miao [A senior manager of Autodesk].

 

I’ll try to keep doing this, delivering a message to the whole team on weekly basis to share whatever I think that is worth sharing.

 

This week I would like to talk about iteration – a method to seek continuous improvement. The thoughts from “The Story of the Ribbon” presentation about how Microsoft put tremendous design effort to design Office 2007 new UI – Ribbon. I’m not sure whether it is true but from the presentation they drew a conclusion: for new designs, you need to at least do three iterations to get it right. Let’s not talk about whether it’s three iteration or four iteration to get it right, which is not the whole point I’m talking about here.

 

The idea is very simple and everybody understands it: we first create something and then we evaluate it and solicit feedbacks and then we make it better according to all feedbacks. This is one cycle or iteration. And then we do it all over again to get it better, and again to make it even better.

 

Let’s now think about how many things we’re doing everyday fall into this method.

1.      Code review is definitely one type of iteration. We proposed the code change (create something) and involve senior people to review (solicit feedbacks) and we make changes according to feedbacks. This is one iteration. Usually we need to do two or three this kind of iteration to get it right.

2.      Design document review. This usually involve even more iterations to get it right. We send the document to all relevant parties to seek feedbacks.

3.      Our product release cycle. Typically we have a yearly release cycle for our major products. We created the product from June to Nov/Dec and initiated Beta programs as initial iterations – getting feedbacks from our beta users to make new release right. After we final release the product to our customers, we still have various approaches to seek customers’ feedbacks on new products.

 

So this whole thing (iteration) is not new to everybody.

The first point I have here is to raise everybody’s awareness. You need several iterations to get it right, to get continuous improvements. For everything you do and you create, if you find you’re not doing iteration, you need to seriously think about why is that and how to make iteration happen.

 

The second important point is how many iterations you need and how long each iteration lasts. Different people may have different habits. Some people prefer to work out the whole thing before they start soliciting feedbacks, whereas some other people prefer to break down the whole thing into small pieces and whenever they create a small piece they start asking for feedbacks. Generally I prefer shorter iterations to get more timely and early feedbacks to prevent bigger cost to fix something not right in the later stages of the game.  Shorter iterations is also heart of Agile practices. I strongly encourage everybody to change your habit to constantly seek feedbacks whenever you create something, don’t wait till the end to get the feedbacks. If you do that (late feedbacks or reactively get feedbacks), you will have less chance to make it right.

 

The third point is how you get feedbacks: Code review and design review is one way to get feedbacks for the things (code and document) we created. But you may ignore that the real thing you are creating is the software. The best way to get feedbacks for the software is to have people use it. For most of the people in our team, you are creating something not for our end customers. Instead, you are creating something for our internal customers (Acad, Inventor, Revit, 3DSMax, Maya, etc). We all need to figure out a good process to seek feedbacks from them. While at the same time, we need think hard all kinds of creative ideas to dog-food the things we create. We are creating sample applications (which really should be called test shell applications) to test our component. We should engage our QA people to do more inspection and testing to provide timely and early feedbacks.

 

Again, the key thing here is “timely and early feedbacks”. By having shorter iterations, we will be able to achieve that.

 

Last, sorry for bad writing here. I just have something and I rush them out in an emai.

Cheers,

Wesley

ReadDirectoryChangesW

Just find a attractive API unexpectedly, ReadDirectoryChangesW can be used to watch a directory. Whenever there occurs an operation on/inside it, we can get notified with information of the operation which file/subdirectory is on, and even their names. Someone on the CodeProject has already attached a wrapped library to do the same thing, with calling ReadDirectoryChangesW under the hood. 🙂

After survey the MSDN, I also found another 3 API group used to watch a directory: FindFirstChangeNotification, FindNextChangeNotification, and FindCloseChangeNotification. The shorti coming of these 3 APIs is that they seem not be able to get the enough information on what happened there.

Below is the simplest demo code used to watch a directory, I use it in a synchronous way. (Some advanced usage of it will involve IO Completion Routine, but since it is too small here, I don’t think IO Completion is suitable for my demo code here).

#include "stdafx.h"
#include "windows.h"

void DumpChangesInfo(const PFILE_NOTIFY_INFORMATION fni);
void StartWatchDirectory(const TCHAR * strDirectoryName);

int _tmain(int argc, _TCHAR* argv[])
{
 if (argc != 2)
  return 0;
 StartWatchDirectory(argv[1]);
 return 0;
}

void StartWatchDirectory(const TCHAR * strDirectoryName)
{
 HANDLE hDirectory;

 hDirectory = CreateFile(
  strDirectoryName,               // Directory name/path
  FILE_LIST_DIRECTORY | FILE_TRAVERSE | GENERIC_READ, // Desired Access
  FILE_SHARE_WRITE | FILE_SHARE_READ,       // File shared mode
  NULL,
  OPEN_EXISTING,
  FILE_FLAG_BACKUP_SEMANTICS,          // Flags and Attributes
  NULL
  );

 if (hDirectory == INVALID_HANDLE_VALUE)
 {
  printf("Error Code[%d]: Open Directory Failed…\n", GetLastError());
  return;
 }

 BYTE buffer[1024] = { 0 }; // hardcode the length of the buffer, ReadDirectoryChangesW may return 0 in dwBytesRet.

 BOOL bResult = FALSE;
 FILE_NOTIFY_INFORMATION * fni = NULL;
 DWORD dwBufferLen = 0;
 DWORD dwBytesRet = 0;
 DWORD dwNotifyFilter =
  FILE_NOTIFY_CHANGE_FILE_NAME |
  FILE_NOTIFY_CHANGE_DIR_NAME |
  FILE_NOTIFY_CHANGE_ATTRIBUTES |
  FILE_NOTIFY_CHANGE_SIZE  |
  FILE_NOTIFY_CHANGE_LAST_WRITE |
  FILE_NOTIFY_CHANGE_LAST_ACCESS |
  FILE_NOTIFY_CHANGE_CREATION |
  FILE_NOTIFY_CHANGE_SECURITY; // Notify for every operations

 printf("Directory Changes is starting…\n");

 do
 {
  ZeroMemory(&buffer, 1024);
  bResult = ReadDirectoryChangesW(
   hDirectory,     // Directory handle
   (LPVOID)&buffer,   // Buffer
   1024,       // Length of the buffer
   TRUE,       // If watch sub directory
   dwNotifyFilter,    // NotifyFilter
   &dwBytesRet,    // Number of Byte returned
   NULL,       // OVERLAPPED structure
   NULL       // IO Completion Routine
   );

  if (bResult == 0)
  {
   printf("Error Code[%d]: Read Directory Changes Failed…\n", GetLastError());
   break;
  }
  fni = (PFILE_NOTIFY_INFORMATION)&buffer;
  DumpChangesInfo(fni);
 } while(bResult);

 printf("Directory Watcher is shutting down…\n");
 CloseHandle(hDirectory);
}

void DumpChangesInfo(const PFILE_NOTIFY_INFORMATION fni)
{
 // FileNameLength returned in PFILE_NOTIFY_INFORMATION is a WCHAR * without ‘0\’ as its termination.
 WCHAR * strFileName = (WCHAR * )malloc(fni->FileNameLength + sizeof(WCHAR));
 wcscpy(strFileName, fni->FileName);
 strFileName[fni->FileNameLength/sizeof(WCHAR)] = _T(”);

 TCHAR strAction[20];
 memset(&strAction, ”, 20 * sizeof(TCHAR));
 switch (fni->Action)
 {
 case FILE_ACTION_ADDED:
  _tcscpy(strAction, _T("ADD"));
  break;
 case FILE_ACTION_REMOVED:
  _tcscpy(strAction, _T("REMOVED"));
  break;
 case FILE_ACTION_MODIFIED:
  _tcscpy(strAction, _T("MODIFIED"));
  break;
 case FILE_ACTION_RENAMED_OLD_NAME:
  _tcscpy(strAction, _T("RENAMED"));
  break;
 case FILE_ACTION_RENAMED_NEW_NAME:
  _tcscpy(strAction, _T("RENAMED"));
  break;
 }

 _tprintf(_T("\tFile/Directory:\t%s -> %s\n"), strFileName, strAction);
 free(strFileName);
}

[Update] Just a minute ago,  I found another guy posted a more object-oriented sample code >”<
http://blog.vckbase.com/bruceteen/articles/229.html

About Calling Convention

[A series of posts on the topics of Calling Convention, by RAYMOND CHEN – MSFT, The Old New Thing]
 
Those posts are tedious sufficiently, however, are still worthy of reading. You will get a rough idea about the road map of how calling convention is being developed, how calling convention is related to a specific architecture of CPU, how calling convention changes from 16-bit to 32-bit, and eventually to 64-bit architecure of CPU. You will also find some famous CPU listed in the posts, e.g., Power PC (PPC, which is a abandon-a-baby of Steve Jobs’s), Intel IA64 (Itanium), and AMD64 (AKA, a x86 architectured CPU with 64-bit extension).
 
[Discussed __cdecl (C Calling Convention), __pascal/__fortran, __fastcall]
 
[Discussed RISC-styled instruction set of CPU, Alpha AXP, MIPS R4000, Power PC]
Great tip: Curiously, it is only the 8086 and x86 platforms that have multiple calling conventions. All the others have only one!
 
[Discussed 32-bit version on the contrary of 16-bit in Part 1, and also thiscall (implicitly used when programming in C++)]
 
[Intel IA64]
 
[AMD 64]
 
Some terminologies in Part 4, 5 are a little difficult for me to understand, definitely, I lose most ideas on 64-bit world. But, I’m confident. Some day in the future, if I look back to this topic, I will have already been clear with them. haha~~~