1

I'm making a profiler in a project, and I want to make it easy to integrate into my projects. I'm using penter and pexit with the /GH /Gh compiler flags so those functions are called every time a function is called or returned from. Right now, basically all I have to do in my projects is copy over the penter and pexit function anywhere in the global scope and that works, but I want to make a macro so it just basically inserts the function in. I defined the macro in my Profiler.h file and included that in my other project. the errors i'm getting are

error C2598: linkage specification must be at global scope
error C2601: '_pexit' : local function definitions are illegal
error C1075: end of file found before the left brace '{' at 'path/main.cpp' was matched

note that 'path/main.cpp' is a long path to my project (non-profiler project) and main is where i'm 'calling' the macros

here are my macros, I must be understanding these wrong. I figured it'd just insert the function where it was 'called'

#define PENTER                                           \
extern "C" void __declspec(naked) _cdecl _penter(void)   \
{                                                        \
  _asm push ebp;                                         \
  _asm mov ebp, esp;                                     \
  _asm pushad;                                           \
  Profiler::GetInstance().Enter();                       \
  _asm popad;                                            \
  _asm mov esp, ebp;                                     \
  _asm pop ebp;                                          \
  _asm ret;                                              \
}                                                        \


#define PEXIT                                            \
extern "C" void __declspec(naked) _cdecl _pexit(void)    \
{                                                        \
  _asm push ebp;                                         \
  _asm mov ebp, esp;                                     \
  _asm pushad;                                           \
  Profiler::GetInstance().Exit();                        \
  _asm popad;                                            \
  _asm mov esp, ebp;                                     \
  _asm pop ebp;                                          \
  _asm ret;                                              \
}                                                        \

Thanks for any help!

user2013535
  • 73
  • 1
  • 1
  • 7

2 Answers2

0

You are most likely missing a } at some place before your profiler.h.

I would use an inline function instead of a multiline macro.

extern "C" inline void __declspec(naked) _cdecl _pexit(void) {
_asm pushad; Profiler::GetInstance().Exit(); _asm popad; _asm ret; }

(That way, it's actually possible to step into the function when debugging - at least in debug mode when it's not inlined).

I also removed the completely unnecessary esp/ebp saving and restoring - PUSHAD will save all registers for you (even esp) [and technically, you only need to save/restore the scratch registers, EAX, ECX and EDX, as all other registers must be saved by the function(s) you call.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
0

You can try micro-profiler to do the task. Or take it's source for collection from here: hooks.asm The good thing about it is that it works for x64 as well (you cannot inject assembly instructions in x64 cpp).

Arty
  • 723
  • 5
  • 10