+3  A: 

Look at the *.map file which can optionally be generated by the linker when it links the program, or at the program's debug (*.pdb) file.

ChrisW
Ah, of course! I don't know why I didn't think of using the PDB file. That's what I need to do exactly, thank you.
LCC
+6  A: 

This won't work. You're presuming functions are contigous in memory and that one address will map to one function. The optimizer has a lot of leeway here and can move code from functions around the image.

If you have PDB files, you can use something like the dbghelp or DIA API's to figure this out. For instance, SymFromAddr. There may be some ambiguity here as a single address can map to multiple functions.

I've seen code that tries to do this before with something like:

#pragma optimize("", off)
void Foo()
{
}

void FooEnd()
{
}
#pragma optimize("", on)

And then FooEnd-Foo was used to compute the length of function Foo. This approach is incredibly error prone and still makes a lot of assumptions about exactly how the code is generated.

Michael
The best that can be done here is to analyze opcodes starting from pointer to beginning on function, do flow analysis on all possible conditional branches, and figure out if your destination instruction pointer is reachable for some possible input. Naturally, this is extremely architecture-specific (any introduction of new opcodes in new CPUs can break this), and very complicated.
Pavel Minaev
SymFromAddr is probably the best and most reliable option.
Dan Moulding
+1  A: 

OK, I haven't done assembly in about 15 years. Back then, I didn't do very much. Also, it was 680x0 asm. BUT...

Don't you just need to put a label before and after the function, take their addresses, subtract them for the function length, and then just compare the IP? I've seen the former done. The latter seems obvious.

If you're doing this in C, look first for debugging support --- ChrisW is spot on with map files, but also see if your C compiler's standard library provides anything for this low-level stuff -- most compilers provide tools for analysing the stack etc., for instance, even though it's not standard. Otherwise, try just using inline assembly, or wrapping the C function with an assembly file and a empty wrapper function with those labels.

Lee B
A: 

Here's how I do it, but it's using gcc/gdb.

$ gdb ImageWithSymbols

gdb> info line * 0xYourEIPhere

Edit: Formatting is giving me fits. Time for another beer.

A: 

The most simple solution is maintaining a state variable:

volatile int FOO_is_running = 0;

int Foo( int par ){
  FOO_is_running = 1;

  /* do the work */

  FOO_is_running = 0;
  return 0;
}
sambowry