Aqua Timez – Velonica

さあ先は见えないこれまでだ
幸せなふりをしていた
もっと走れると言い闻かせて
无谋にもそっと手を掴みあい
来た道を一别一人はごめん四面楚歌戦线に
告ぐ别れる前に问いかけたのにちりは积もってく
果てしない旅の途中で町の外れに立ち寄る疲れた両足を
そっと投げ出して寝転ぶと缲り返される浅い眠り
何度も同じあの横颜何度も同じあの言叶を
生きてるだけで悲しいと思うのは私だけなのと闻いたわ
この烟町を睨み虚ろに消えるきっとまだ力なき幼い日々
见なくていい悲しみを见てきた君は
今こらえなくていい涙をこらえて过ごしてる
本当の事だけで生きていけるほど仆らは强くないさ
强くなくていい
————————————————-
来吧 把这悲伤 掩饰为幸福
说着不要停下脚步 默默地相拥在一起
瞥了一眼来时的路 不禁泪下
也无法掩饰心中的喜悦
把碎片收集
在那无际的旅途中驻足于城市的边际
随意躺倒在地
不断重复的淡淡的回忆
重复着那同样的面容 那同样的话语
只要活着就会感到悲伤的难道只要我吗?那孩子问
相似的经历往往被人忽视
消失在虚无中的必定又是幼小无力的你
一直注视着无须注视的悲伤的你 如今
抑制着无需抑制的泪水一路走来
只是依靠真实而生存
我们还没有如此坚强 不用如此坚强 不用

complaint and abreact

It looks like Nov is my blank, because I didn’t write anything down here. Lazy or busy? Hmm…Answer is both laziness and busyness. In fact, I still keep my learning steps for a work around of getting mixed mode callstacks from dump file. I used to think I would reach my goal. But, surely, I failed eventually. F**K!!!

As Visual Studio can do interop debugging (native + managed), that is known to all that it is totally based on ICorDebug API (Debugging API shipped in .NET Framework), so I took great pains over learning it.

It’s very soon that I came to realize it is a steep learning curve. The documentation as to ICorDebug API is really poor and tedious, even though, it’s the only way to start off learning, no step by step programming guide available (Some official documents shipped in previous version of .NET Framework SDK seem like not available now.hmm…). I got most of valuable information from Mike Stall’s blog (an expert in MS ICorDebug Team), but most of his articles are not written for a fresher. So, I read through MSDN and Mike’s blog carefully (via word-splitting), somehow referred to the Sample Code of MDBG, and infer the usage of this set of API. After all, I got a simplest, the most ugly .NET debugger as the code I attached in my last post (of course, the code here is not complete).

ICorDebug is very different from its counterpart Win32 Debugging API. It’s not an OS facilitated debugging technology, which means ICorDebug is not based on Win32 Debugging API, and it has its own mechanism. CLR Debugging service is split in two parts, one in debuggee (so called Left-Side, LS) and another in debugger (so called Right-Side, RS). LS is part of .NET CLR (from our perspective, it is exposed in a form of Helper Thread), while RS is out of process that ICorDebug takes in action that developers need to do the programming here to implement what they want.

What’s not acceptable is because of the architecture design of CLR. ICorDebug in v2.0 (even in interop debugging) is not with dump file debugging support. ICorDebug requires that Helper Thread in debuggee should be running freely. When debugging dump file, this demand is nearly impossible. Hmm… so, ICorDebug is not feasible to our CER System. I have to give it up?? Sh*t!!

Anyway, in MS PDC 2008, Microsoft announced that in .NET CLR 4.0, debugging subsystem will be re-architected with some advanced debugging features added in.  Dump file debugging is one of it. I’m looking forward to… But, seems like windbg+SOS is a more possible direction for my investigation. But how to accomplish it programmatically? This should be my learning topic in the next phase.

Learning Managed Debugging 1 – ICorDebug API – Simply Usage

#define _WIN32_DCOM

#include <windows.h>

 

#include <corhdr.h>

#include <cordebug.h>

#pragma comment(lib, "CorGuids.lib")

 

#include <MSCorEE.h>

#pragma comment(lib, "MSCorEE.lib")

 

#include <iostream>

 

#include "CorDbgManagedCallback.h"

 

int _tmain(int argc, _TCHAR* argv[])

{

          HRESULT hr = E_FAIL;

 

          ICorDebug * debug = NULL;

          ICorDebugProcess* process = NULL;

 

          //////////////////////////////////////////////////////////////////////////

 

          hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); // MTA is a must.

          if (FAILED(hr))

                   goto cleanup;

 

          const wchar_t * szDebuggeeVersion2 = L"v2.0.50727";   // if we’re debugging a v2.0 debuggee.

          const int iDebuggerVersion = CorDebugVersion_2_0;       // if we’re a v2.0 debugger.

 

          // ICorDebug 2.0 requires creating COM object with this method,

          // instead of CoCreateInstance. Versioning issue is resolved here.

          hr = CreateDebuggingInterfaceFromVersion(

                   CorDebugVersion_2_0, szDebuggeeVersion2, (IUnknown**) &debug);

          if (FAILED(hr))

                   goto cleanup;

 

          //////////////////////////////////////////////////////////////////////////

 

          hr = debug->Initialize();

          if (FAILED(hr))

                   goto cleanup;

 

          // Receiving managed debugging event.

          hr = debug->SetManagedHandler(&g_corDbgManagedCallback);

          if (FAILED(hr))

                   goto cleanup;

 

          // Not implementing in this sample code.

          //hr = debug->SetUnmanagedHandler(); // for interop debugging…

 

          STARTUPINFO si;

          PROCESS_INFORMATION pi;

 

          ZeroMemory(&si, sizeof(si));

          si.cb = sizeof(si);

          ZeroMemory(&pi, sizeof(pi));

 

          // Prepare event object to sync debugging event.

          g_event = CreateEvent(NULL, TRUE, FALSE, EVENT_OBJECT);

          if (g_event == NULL)

                   goto cleanup;

 

          // second param of CreateProcess must not be a const string.

          wchar_t buffer[MAX_PATH] = { 0 };

          hr = debug->CreateProcess(

                   L"debuggee.exe",               // Specify executable image of debuggee.

                   buffer,

                   NULL,

                   NULL,

                   FALSE,

                   CREATE_NEW_CONSOLE,

                   NULL,

                   NULL,

                   &si,

                   &pi,

                   DEBUG_NO_SPECIAL_OPTIONS,

                   &process

                   );

          if (FAILED(hr))

                   goto cleanup;

 

          // We still need to close this two handles, since they are useless

          // to debugger!!!

          CloseHandle(pi.hThread);

          CloseHandle(pi.hProcess);

 

          while (true)

          {

                   // Resume after ICorDebugManagedCallback::ExitProcess event.

                   WaitForSingleObject(g_event, INFINITE);

                   break;

          }

 

          // Terminate should not be called until an

          // ICorDebugManagedCallback::ExitProcess callback has been

          // received for all processes being debugged.

          hr = debug->Terminate();

          if (FAILED(hr))

                   goto cleanup;

 

          //////////////////////////////////////////////////////////////////////////

 

cleanup:

 

          if (process != NULL)

                   process->Release();

 

          if (debug != NULL)

                   debug->Release();

 

          if (g_event != NULL)

                   CloseHandle(g_event);

 

          CoUninitialize();

 

          return 0;

}

Austin.D @ Autodesk

Get stack trace from dump file

In the last several posts, I attached URLs of a serials of blog posts that describe how to automate dump file analysis. One of the posts gives out a solution on how to dump stack trace. Even though, it’s pity that author did not dump out stack trace for a crash context. After reading documentation, and overcome those damn debugger concepts, I comes to the following code excerpt.
 
Two functions need to be highlighted: IDebugAdvanced2::Request, IDebugControl4::GetContextStackTrace. Use Request to get register context information of the last event stored in dump file, where last event is usually an exception that we are of interest; Use GetContextStackTrace to get stack trace related to the previous register context.
 

HRESULT DumpStackEx(IDebugSymbols *symbols, IDebugAdvanced2 *advanced2, IDebugControl4 *control4)

{

          HRESULT hr = S_OK;

 

          CONTEXT _context = { 0 };

          ULONG _uOutSize = 0;

 

          hr = advanced2->Request(DEBUG_REQUEST_TARGET_EXCEPTION_CONTEXT,

                   NULL, 0, &_context, sizeof(CONTEXT), &_uOutSize);

          if(FAILED(hr))

          {

                   goto cleanup;

          }

 

          DEBUG_STACK_FRAME _stackFrames[256] = { 0 };

          CONTEXT _frameContexts[256] = { 0 };

          ULONG _uFramesFilled = 0;

          hr = control4->GetContextStackTrace(&_context, sizeof(_context), _stackFrames, ARRAYSIZE(_stackFrames),

                   _frameContexts, 256 * sizeof(CONTEXT), sizeof(CONTEXT), &_uFramesFilled);

          if(FAILED(hr))

          {

                   goto cleanup;

          }

         

          printf("Stack Trace:\n");

 

          for(ULONG _uFrame = 0; _uFrame < _uFramesFilled; _uFrame++)

          {

                   HRESULT symhr;

                   char _name[512];

                   unsigned __int64 offset = 0;

                   ULONG _uLineNo = 0;

 

                   ZeroMemory(_name, ARRAYSIZE(_name));

                   symhr = symbols->GetNameByOffset(_stackFrames[_uFrame].InstructionOffset,

                             _name, ARRAYSIZE(_name) – 1, NULL, &offset);

 

                   if(SUCCEEDED(symhr))

                   {

                             printf("%s+0x%I64X", _name, offset);

                   }

                   else

                   {

                             printf("0x%08I64X", _stackFrames[_uFrame].InstructionOffset);

                   }

 

                   ZeroMemory(_name, ARRAYSIZE(_name));

                   symhr = symbols->GetLineByOffset(_stackFrames[_uFrame].InstructionOffset,

                             &_uLineNo, _name, ARRAYSIZE(_name) – 1, NULL, NULL);

 

                   if(SUCCEEDED(symhr))

                   {

                             printf(" [%s(%u)]", _name, _uLineNo);

                   }

                   printf("\n");

          }

 

cleanup:

 

          return hr;

}

Austin.D @ Autodesk

Get modules’ info from dump file

Code snippet for programmatically abtaining modules’ info from dump file. Some useful information, such as Timestamp and ImageSize.
 
1. Get interface pointers necessarily when accessing functionalities available from dbgeng.dll
 

hr = client->QueryInterface(__uuidof(IDebugControl), (LPVOID*)&control);

hr = client->QueryInterface(__uuidof(IDebugSymbols), (LPVOID*)&symbols);

hr = client->QueryInterface(__uuidof(IDebugSymbols2), (LPVOID*)&symbols2);

2. Set Symbol Search Path, and Image Search Path. Then open dump file
 

symbols->SetSymbolPath("D:\\Dotfuscated\\old_version;symsrv*symsrv.dll*C:\\sc\\ms*http://msdl.microsoft.com/download/symbols");

symbols->SetImagePath("D:\\Dotfuscated\\old_version");hr = client->OpenDumpFile("D:\\Dotfuscated\\old_version\\vb_filter_wrapper.dmp");

 
3. Dump all loaded and unloaded modules’ information
 

HRESULT DumpModule(IDebugControl *control, IDebugSymbols *symbols, IDebugSymbols2 *symbols2)

{

          HRESULT hr = S_OK;

 

          ULONG uloadedModules = 0;

          ULONG uUnloadedModules = 0;

 

          // Get number of both loaded and unloaded modules.

          hr = symbols->GetNumberModules(&uloadedModules, &uUnloadedModules);

          if (FAILED(hr))

          {

                   goto cleanup;

          }

 

          ULONG uTotal = uloadedModules + uUnloadedModules;

 

          DEBUG_MODULE_PARAMETERS* pDebugModParam =

                   (DEBUG_MODULE_PARAMETERS*)_malloca(uTotal * sizeof(DEBUG_MODULE_PARAMETERS));

 

          hr = symbols->GetModuleParameters(uTotal, NULL, 0, pDebugModParam);

          if (FAILED(hr))

          {

                   goto cleanup;

          }

 

          for (int i = 0; i < uTotal; i++, pDebugModParam++)

          {

                   char buffer[MAX_PATH] = { 0 };

                   hr = symbols2->GetModuleNameString(DEBUG_MODNAME_IMAGE, i, NULL, buffer, MAX_PATH, NULL);

                   if (FAILED(hr))

                   {

                             continue;

                   }

                   printf("ImageName: %s\n", buffer);

                   printf("-Base: 0x%I64X\tImageSize: 0x%I32X\tTimestamp: 0x%I32X\n",

                            pDebugModParam->Base, pDebugModParam->Size, pDebugModParam->TimeDateStamp);

          }

 

cleanup:

          if (pDebugModParam != NULL)

          {

                   _freea(pDebugModParam);

          }

         

          return hr;}