Обновление Этот ответ устарел для последней версии .NET: см. Здесь Как получить текущее значение EIP в управляемом коде?
Очень краткий ответ: виртуальная машина CLR - это стековая машина, поэтому EIP там нет .Немного более длинный ответ: если вы полагаетесь на недокументированные подробности, относящиеся к реализации, вы можете экстраполировать пригодный идентификатор из EIP ЦП в неуправляемый код.
Подтверждение концепции
Я простосправился со следующим подтверждением концепции, используя моно 2.11 в 32-битной LinuxЯ надеюсь, что информация может помочь.Это реализует неуправляемые функции:
extern static string CurrentMethodDisplay();
extern static uint CurrentMethodAddress();
Собственный источник: tracehelper.c [1]:
#include <string.h>
void* CurrentMethodAddress()
{
void* ip;
asm ("movl 4(%%ebp),%0" : "=r"(ip) );
return ip;
}
const char* const MethodDisplayFromAddress(void* ip);
const char* const CurrentMethodDisplay()
{
return MethodDisplayFromAddress(CurrentMethodAddress());
}
#ifndef USE_UNDOCUMENTED_APIS
extern char * mono_pmip (void *ip);
const char* const MethodDisplayFromAddress(void* ip)
{
const char* text = mono_pmip(ip);
return strdup(text? text:"(unknown)");
}
#else
/*
* undocumented structures, not part of public API
*
* mono_pmip only returns a rather ugly string representation of the stack frame
* this version of the code tries establish only the actual name of the method
*
* mono_pmip understands call trampolines as well, this function skips those
*/
struct _MonoDomain; // forward
struct _MonoMethod; // forward
typedef struct _MonoDomain MonoDomain;
typedef struct _MonoMethod MonoMethod;
struct _MonoJitInfo { MonoMethod* method; /* rest ommitted */ };
typedef struct _MonoJitInfo MonoJitInfo;
MonoDomain *mono_domain_get(void);
char* mono_method_full_name(MonoMethod *method, int signature);
MonoJitInfo *mono_jit_info_table_find(MonoDomain *domain, char *addr);
const char* const MethodDisplayFromAddress(void* ip)
{
MonoJitInfo *ji = mono_jit_info_table_find (mono_domain_get(), ip);
const char* text = ji? mono_method_full_name (ji->method, 1) : 0;
return text? text:strdup("(unknown, trampoline?)");
}
#endif
C # Source (client.cs) для вызова этой собственной функции библиотеки:
using System;
using System.Runtime.InteropServices;
namespace PoC
{
class MainClass
{
[DllImportAttribute("libtracehelper.so")] extern static string CurrentMethodDisplay();
[DllImportAttribute("libtracehelper.so")] extern static uint CurrentMethodAddress();
static MainClass()
{
Console.WriteLine ("TRACE 0 {0:X8} {1}", CurrentMethodAddress(), CurrentMethodDisplay());
}
public static void Main (string[] args)
{
Console.WriteLine ("TRACE 1 {0:X8} {1}", CurrentMethodAddress(), CurrentMethodDisplay());
{
var instance = new MainClass();
instance.OtherMethod();
}
Console.WriteLine ("TRACE 2 {0:X8} {1}", CurrentMethodAddress(), CurrentMethodDisplay());
{
var instance = new MainClass();
instance.OtherMethod();
}
Console.WriteLine ("TRACE 3 {0:X8} {1}", CurrentMethodAddress(), CurrentMethodDisplay());
Console.Read();
}
private void OtherMethod()
{
ThirdMethod();
Console.WriteLine ("TRACE 4 {0:X8} {1}", CurrentMethodAddress(), CurrentMethodDisplay());
}
private void ThirdMethod()
{
Console.WriteLine ("TRACE 5 {0:X8} {1}", CurrentMethodAddress(), CurrentMethodDisplay());
}
}
}
Компилировать и связывать, используя Makefile:
CFLAGS+=-DUSE_UNDOCUMENTED_APIS
CFLAGS+=-fomit-frame-pointer
CFLAGS+=-save-temps
CFLAGS+=-g -O3
all: client.exe libtracehelper.so
client.exe: client.cs | libtracehelper.so
gmcs -debug+ -optimize- client.cs
tracehelper.s libtracehelper.so: tracehelper.c
gcc -shared $(CFLAGS) -lmono -o $@ tracehelper.c
# gcc -g -O0 -shared -fomit-frame-pointer -save-temps -lmono -o $@ tracehelper.c
test: client.exe
LD_LIBRARY_PATH=".:..:/opt/mono/lib/" valgrind --tool=memcheck --leak-check=full --smc-check=all --suppressions=mono.supp mono --gc=sgen --debug ./client.exe
clean:
rm -fv *.so *.exe a.out *.[iso] *.mdb
Запуск с LD_LIBRARY_PATH=. ./client.exe
приводит к:
TRACE 0 B57EF34B PoC.MainClass:.cctor ()
TRACE 1 B57EF1B3 PoC.MainClass:Main (string[])
TRACE 5 B57F973B PoC.MainClass:ThirdMethod ()
TRACE 4 B57F96E9 PoC.MainClass:OtherMethod ()
TRACE 2 B57EF225 PoC.MainClass:Main (string[])
TRACE 5 B57F973B PoC.MainClass:ThirdMethod ()
TRACE 4 B57F96E9 PoC.MainClass:OtherMethod ()
TRACE 3 B57EF292 PoC.MainClass:Main (string[])
Обратите внимание, что это в Mono 2.11.Также работает на 2.6.7, с оптимизацией и без.
[1] Я выучил GNU, расширенный asm для этой цели;спасибо SO!
Выводы?
Предоставлено подтверждение концепции;эта реализация специфична для Mono.Подобный «трюк» может быть реализован в MS .Net (с использованием :: LoadLibrary SOS.dll , возможно?), Но оставлен в качестве упражнения для читателя:)
Я бы лично все равно пошел бы с другим моим ответом , но я полагаю, что я уступил вызову, и, как я уже говорил: YMMV, здесь будут драконы, TIMTOWTDI , KISSи т.д.
Спокойной ночи