スタックトレースを取る。

Windowsスタックトレースを取ろうと思えば、
.NETを使えばSystem.DiagnosticsにあるStackTraceクラスとかで簡単に取れるらしい。

さて、今のプロジェクトはMFCなのでCLRを使えない?
よく知らないけど、出来たとしても、出来るまでが大変そう。

VC++インラインアセンブラを使えば、スタックのフレームとリターンアドレスを取るくらいは簡単そう。

#pragma once

#include <boost/format.hpp>
#include <pstade/oven/foreach.hpp>
#include <pstade/oven/counting.hpp>

namespace hwm
{

template<typename Strm>
Strm& StackTracer(Strm& s, unsigned int num_of_trace = -1)
{
	int esp_;
	int ebp_;
	int addr_;
	{
		__asm mov esp_, esp;	//get esp
		__asm mov ebp_, ebp;	//get ebp
	}

	s << "//==============================================//" << std::endl;

	try {
		PSTADE_OVEN_FOREACH(i, pstade::oven::counting(0, num_of_trace)) {
			{
				__asm mov ebx, ebp_;
				__asm mov eax, [ebx];		//get 'prev'ebp
				__asm push eax;			//save
				__asm mov eax, ebp_;		
				__asm mov esp_, eax;		//esp = ebp('prev'esp)
				__asm pop eax;			//restore
				__asm mov ebp_, eax;		//ebp = 'prev'ebp
				__asm mov ebx, ebp_;
				__asm add ebx, 4;
				__asm mov eax, [ebx];		//return address
				__asm mov addr_, eax;
			}

			s << boost::format("esp : %08x, ebp : %08x, ret_addr : %08x") % esp_ % ebp_ % addr_ << "\n";
		}
	} catch(...) {
		s << "!!Out of stack Access!!" << std::endl;
	}

	s << "//==============================================//\n" << std::endl;
	return s;
}

}

ここから関数名を割り出したりとかって言うのは、ソース上から出来るもんなのだろうか?
ちなみに、当たり前だけど、VC++のコード生成はSEHの例外を捕捉できるようにしておかないと、落ちる。