SPRAB89A September 2011 – March 2014
In general since callees are responsible for setting up their own DP, no special handling is required for function pointers. Exported functions can safely be called indirectly from inside or outside the module where they are defined. (This is a major advantage of the DSBT model over some of the other MMU-less approaches.)
However, there is a potential pitfall in the use of function pointers. If a function with internal visibility has its address taken, passed to another static link unit, and then indirectly called, it likely will not set the DP properly and the program will fail.
Taking the address of an internal function and making it available to another module is, strictly speaking, a programming error since it violates the assumptions implied by the visibility declaration. To aid in detecting such violations the toolchain may choose to have the compiler issue a warning when the address of a non-exported function is taken. Users who are doing so legitimately can disable the warning.
Taking the address of an external function and passing it to another module is always legitimate. To permit comparison of function pointers computed in different modules to work as expected, the ABI requires that an expression representing the address of a function evaluates to a unique value across all modules. Some ABIs for other architectures adopt a convention that, within an executable, references to the address of a function may resolve to the PLT entry, allowing for static resolution of those references. (References from a shared object must resolve dynamically, due to preemption).
The C6000 ABI does not adopt that convention because it leads to a problem with cross-module calls through a function pointer. If such a pointer could resolve to a PLT entry, then when an indirect call lands at that PLT entry the DP value may be that of a different static link unit, preventing the PLT entry from being able to access the GOT. In effect the PLT entry is an internal function so it must not be called indirectly from outside the module.
Therefore, the convention for the C6000 ABI is that a reference to the address of a function must resolve to the function's actual address. The implication is that for imported objects, such references cannot be statically resolved; they must be resolved at load time by the dynamic linker.