Overriding a 'C' function in a static library (.a)

M

mpatnam

I have an executable which links to a static library (.a).
I want to provide a hook by overriding a function part of this static
library.
Eg: I have a function "int blkstart(int i)" in this static library.
I want to override this by having another function which is exactly
similar in signature including name.
When somebody call this function, control should automatically come to
my overriddent function. Inside this function, based on certain
conditions, I would like to call the original function in the static
library.

I tried using dlsym and dlopen APIs under SUN Solaris, but it didn't
work as I suppose it is not meant for static library.
Also I think this is the reason why it didn't work with static lib:

Since static lib (.a) doesn't have identity at runtime like dlls, only
the first available symbol was taken by linker during linking time and
ignores any duplicate symbols available in any other
static libs. At runtime, there is no way we can get the address of the
duplicate
function residing in the static library. Even running "nm <exe>" shows
only one
symbol which is the overloaded one (as in the make file, I have .o
file ahead of
-l<static-lib>). Basically at runtime, dlsym() can never resolve the
duplicate function address as to start with, it was part of a static
lib and linker ignores it as it has already resolved that symbol from
the overloaded function.


I would like to know if there is any other approach to fix this
problem. Note that I don't have freedom to convert this static lib to
dynamic one.
 
E

Eric Sosman

mpatnam said:
I have an executable which links to a static library (.a).
I want to provide a hook by overriding a function part of this static
library.

The details of how to do this (or whether it can be done
at all) are specific to your platform, and really have nothing
to do with the C language. However:
Eg: I have a function "int blkstart(int i)" in this static library.
I want to override this by having another function which is exactly
similar in signature including name.
[...]
I would like to know if there is any other approach to fix this
problem. Note that I don't have freedom to convert this static lib to
dynamic one.

The C-and-nothing-but-C answer is to recompile all
of the calling program, adding

#define blkstart my_blkstart

at the beginning of each translation unit ("source file")
except for the file where my_blkstart is defined. Note
that this will work only for those sources you can recompile;
if the .a library itself contains un-recompilable functions
that call blkstart(), this technique will not catch those
calls.
 
K

Kelsey Bjarnason

I have an executable which links to a static library (.a). I want to
provide a hook by overriding a function part of this static library.
Eg: I have a function "int blkstart(int i)" in this static library. I
want to override this by having another function which is exactly
similar in signature including name.
When somebody call this function, control should automatically come to
my overriddent function. Inside this function, based on certain
conditions, I would like to call the original function in the static
library.

Closest thing I can think of would be a macro. That is, do something
like:

#define blkstart mynewblkstart

then, in mynewblkstart.c:

#undef blkstart

int mynewblkstart(int i )
{
return blkstart( i );
}

You'll just have to ensure that anyone calling blkstart also has the
appropriate header included (to get the macro).
 
D

Derk Gwen

(e-mail address removed) (mpatnam) wrote:
# I have an executable which links to a static library (.a).
# I want to provide a hook by overriding a function part of this static
# library.
# Eg: I have a function "int blkstart(int i)" in this static library.
# I want to override this by having another function which is exactly
# similar in signature including name.

Once an external symbol is defined in a running program, you'll have
little or no chance to redefine it.


An alternative scheme is to something like

plover.h
typedef int (*BlkStartFunc)(int);
void defineBlkStartFunc(BlkStartFunc);
plover.c
int default_blkstart(int) {
your current blkstart routine goes here
};
static BlkStartFunc blkstart = default_blkstart;
void defineBlkStartFunc(BlkStartFunc f) {
blkstart = f;
}

Thus if your client does nothing, they use your default blkstart. If they
want to override that, rather than depend on something tricky with the loader,
they just call defineBlkStartFunc with their own blkstart routine. Within
your code, you still call blkstart(x) the same as always.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top