Accessing program counter / instruction pointer

How does one transfer the program counter / instruction pointer to a variable in C++?

I want to be able to:
1) obtain the current execution address
2) pass that address to another function (f)
3) in function (f), check the integrity of the calling function's code and/or modify it

This seems to require at least some assembly code. I presume that I could check the actual addresses in question in a disassembler and hard-code them into my program, but that would be tedious.

Relatedly:
1) How to obtain the start address of a function?
2) How to obtain the address of a label?

In C++ (VC5) I always get the error: 'illegal operation on bound member function expression' when I try to take the address of a function.
eleighAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

NickRepinCommented:
#include <windows.h>
#include <iostream.h>
#include <stdio.h>

void a()
{
   cout<<"a() func"<<endl;
}

void aendmark() { }

void main(void)
{
   DWORD current_instruction_pointer;
   DWORD label_address;
   DWORD function_address;

   cout<<"Obtain current value of instruction pointer"<<endl;

   __asm {
label1:
      mov current_instruction_pointer,offset label1
   }

   cout<<"Obtain label address"<<endl;

   __asm {
      mov label_address,offset label2
   }


   cout<<"Obtain function address"<<endl;
   
   function_address=DWORD(a);

   cout<<current_instruction_pointer<<endl;
   cout<<label_address<<endl;
   cout<<function_address<<endl;

label2:
   exit(0);
}

0
eleighAuthor Commented:
Good answer, thanks, except ... taking the address of a function in C++ only works when it's global (or perhaps when it's a member of a static class), but not when it's an ordinary class function (sorry, should have made that clearer before):

MyClass::func1()
{
  void *ptr1 = [address of this->func1()]
  void *ptr2 = [address of this->func2()]
}

MyClass::func2()
{
....
}
0
NickRepinCommented:
It is not necessary to reject my answer, especially if it is "Good".

#include <windows.h>
#include <iostream.h>

class A
{
   public:
       void f1();

  typedef void (A::*pfunc) ();
};

void A::f1()
{
   A a;
   union {
      A::pfunc p;
      DWORD addrf1;
   } u;
   u.p=this->f1;
   cout<<hex<<u.addrf1<<endl;

}

void main(void)
{
   A a;
   union {
      A::pfunc p;
      DWORD addrf1;
   } u;
   u.p=a.f1;
   cout<<hex<<u.addrf1<<endl;
   a.f1();
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

NickRepinCommented:
Sorry,   " A a; " in f1() is not necessary.
   
0
NickRepinCommented:
Sorry again, the code above returns not the address of the function itself, but the address of jmp instruction that points to this function. I'll fix this in minutes.
0
NickRepinCommented:
This code works fine for Borland compiler. For VC++ you have to use the following (note: you can use A::f1 instead of a.f1)

#include <windows.h>
#include <iostream.h>

// This is VC++ specific.
void fixVC(DWORD& addr)
{
#pragma pack(push,1)  
   typedef struct {
      char opcode;
      DWORD offset;
   } *pjmp;
#pragma pack(pop)
   pjmp jmp=(pjmp) addr;
   addr=addr+sizeof(*jmp)+jmp->offset;
}

class A
{
   public:
       void f1();

  typedef void (A::*pfunc) ();
};

void A::f1()
{
   union {
      A::pfunc p;
      DWORD addrf1;
   } u;
   u.p=A::f1;
   fixVC(u.addrf1);
   cout<<hex<<u.addrf1<<endl;

}

void main(void)
{
   A a;
   union {
      A::pfunc p;
      DWORD addrf1;
   } u;
   u.p=A::f1;
   fixVC(u.addrf1);
   cout<<hex<<u.addrf1<<endl;
   a.f1();
}
0
eleighAuthor Commented:
Many thanks! I would have got there eventually with the assembly code, but your fixVC() I wouldn't have worked out for myself. (Sorry about rejecting your original answer: didn't realise I could just add a comment to an answer.)
0
nietodCommented:
nick, what if it is a virtual function?
0
NickRepinCommented:
Is it the new question?
0
nietodCommented:
Huh?  I'm just pointing out that the approach won't work with virtual functions.
0
NickRepinCommented:
Yes, but the author of question is satisfied with my answer. It seems that he uses non-virtual functions. As you can see, this Q is not about theoretical, but about concrete stuff - something like copy protection. Of course, we can extend the Q to virtual functions, virtual base classes etc, but what's for?
0
nietodCommented:
Are you sure he doesn't use virtual functions?  Are you sure he knows and is satisfied that it won't work for virtual functions.?  Could be, I don't know either....
0
NickRepinCommented:
I think, eleigh will add comment about this if he wants.
But it must be something extremely super very cool if there is a need to get a actual memory address of virtual function!
0
nietodCommented:
"extremely super very cool"?  Just "super very cool" wouldn't justify it, then?  alright.  You're probably right....
0
eleighAuthor Commented:
OK, guys, I don't envisage needing the address of a virtual function so let's say we'll 'leave it as an exercise for the reader'. (One that's beyond me though: the address one ends up with is of the 'vcall' code which contains a jmp offset from edx. Haven't a clue how to take it from there, since the value of edx isn't defined unless you're calling the function.)
0
nietodCommented:
When do you end up with this "vcall code"?  with a virtual function?  If so you need to use the offset as an index in the the class's virtual function table.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.