Basically, you're trying to duplicate the actions of a debugger.
Debuggers work by reading the symbol table information which is typically appended to the end of executable files, which at a minimum is the name and address of all the global functions.

Accessing this information is of course implementation specific, but you may be able to find a library or two to make it less painful.