In the following discussion, we use the term "executable" to refer to
either an application or a shared library of either type.
There are two ways a function can be called: either directly, or when its
address is taken and a call is subsequently made through that pointer.
An executable can construct a pointer to a function within itself, or to a
function in a GLib it uses (this will really be a pointer to the relevant
stub), but not to a SysLib or operating system API function (since you can't
construct a pointer to a systrap).
In simple cases, access to globals isn't a major problem:
When an executable E calls another function within E, it's just a
direct subroutine call, and of course E's globals are still available.
When an executable E calls a function in a GLib L, it calls via a
stub linked into E whose job is to set up access to L's globals,
call the function proper, and then restore E's globals afterwards.
Again, the appropriate globals are available.
When an executable calls a function in a SysLib, it calls via a system trap,
which merely finds the library routine and calls it. Thus, in this case, it
is the library routine's responsibility to arrange access to its globals.
When an executable constructs a pointer to a function, and then itself
calls through that pointer, it's again just a direct subroutine call, so its
globals are available.
However, the situation gets more complex when an executable constructs a
pointer to a function and then gives it to someone else, perhaps by passing
it as an argument or by returning it to its caller. "Someone else" may
be either another executable or the operating system (so the pointer is a
"callback function").
The rules here are:
Any pointer constructed by an application will work anywhere.
A pointer constructed by a shared library to a function within that library
will work if that function takes steps to initialise its global pointer
(Note entrypoints.). Feature and trampoline entrypoints are most suitable.
A pointer constructed by a shared library to a function in a separate GLib
will never work at all,
because it is impossible to specify a special entrypoint
sequence for a GLib stub. Fortunately, this can be worked around by adding
a function to the other GLib which returns the required function pointer.
In previous versions of prc-tools, applications also accessed their globals via
the A4 register, and their function pointers were therefore subject to the
same restrictions as shared library function pointers. The appropriate steps
to initialise the global pointer are much simpler for an application than a
shared library, and were available via the macros CALLBACK_PROLOGUE
and CALLBACK_EPILOGUE. This is no longer necessary. However,
if you really want to use `-mown-gp' when building an application,
you can use APP_ENTRYPOINT as a more convenient equivalent of the
CALLBACK_* macros.