Incrementing function pointers

4.7k views Asked by At

I just learned about function pointers (pointers pointing at the adress where where the machine code of a function is stored). This made me think about machine code and how it is stored in memory.

Is the machine code stored consecutively in memory, so that it is possible to "manually" increase the pointer until it points to the following/previous function?

Is this, what a debugger does? He lets me "see" where the program counter is pointing in the machine code?

Conclusion: one can program with function pointers a primitive debugger?

Did I understand this right, or am I way off?

5

There are 5 answers

0
BlueRaja - Danny Pflughoeft On BEST ANSWER

Kind of. You are assuming functions will be layed out in memory the same way they are in the source code. Most likely, they will not be - the compiler usually moves them around all willy-nilly.

What you could do, however, is step through the code with a pointer to the current instruction, and increment that counter by a certain amount to get to the next instruction. However, in that case we would no longer call it a function pointer, since it's not just pointing to the beginning of a function; instead, we'd call it an instruction pointer.

In fact, this is exactly how a computer works - it has a special register called the program counter which always points to the current instruction, and increments it by a certain amount after every instruction (a GOTO command is equivalent to writing a value into the program counter).

In the real world, however, this is not how debuggers work - in fact, I'm not even sure if it's possible to have a pointer point to the code-segment in memory in C, other than a function pointer. More likely, you would only need to use this technique if you needed to simulate a program counter, such as writing an emulator for another processor-type.

0
Vi. On
  1. Machine code can be stored non-consecutively. Compiler feels free to split or merge some functions (in optimisation)
  2. If you manually increase a pointer to function you will probably get into middle of function, which is wrong.
  3. Debugging routines are already available: you can obtain stack traces of current execution point and resolve function names where execution pointers in stack do belongs (man backtrace, man backtrace_symbols). With addr2line you can convert them to line numbers.
0
EboMike On

There is no guarantee as to where individual functions are going to be in memory.

A function itself will be a continuous block of memory (since the CPU executes the instructions sequentially), but if you enable code optimization, it may not resemble the function itself (instructions may be reordered heavily). It could even borrow the clean-up code from a different function.

You could write a primitive debugger, but it won't be trivial to find out where a function ends.

0
Jerry Coffin On

You can (or at least could) do something like this, but it's decidedly non-trivial. First of all, you can't actually increment or decrement a function pointer -- it points to an address, but pointer math is normally done in increments of sizeof(pointed to type) -- but with a function, that isn't meaningful, so you can't do math on it.

Most debuggers work (primarily) by using debugging information that relates address to line numbers, function names, variable names, etc.

2
templatetypedef On

Using a draft C standard that I've managed to track down (N1124), we have similar rules. The section on addition expressions (§6.5.6/2) says that

For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type

And an object type is defined in §6.2.5/1 as

The meaning of a value stored in an object or returned by a function is determined by the type of the expression used to access it. (An identifier declared to be an object is the simplest such expression; the type is specified in the declaration of the identifier.) Types are partitioned into object types (types that fully describe objects), function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes).

Since function types are distinct from object types, this suggests that pointer arithmetic on function pointers is prohibited.

In C++, this operation is illegal. The definition of pointer addition, given in §5.7/1, says the following:

For addition, either both operands shall have arithmetic or enumeration type, or one operand shall be a pointer to a completely defined object type and the other shall have integral or enumeration type.

However, §3.9/9 states that

An object type is a (possibly cv-qualified) type that is not a function type, not a reference type, and not a void type.

Taken together, this means that you cannot increment a function pointer in C++.

Hope this helps!