[bfd] Redirecting function calls in object files

Ames Andreas Andreas.Ames@comergo.com
Fri Apr 28 06:23:00 GMT 2006


Hi Nick,

thanks for your valuable comments.

> -----Original Message-----
> From: Nick Clifton [mailto:nickc@redhat.com] 
> Sent: Tuesday, April 25, 2006 7:10 PM
> Subject: Re: [bfd] Redirecting function calls in object files
> 
> If you have the sources of the classes available, why can't 
> you redirect 
> the calls at the source level ?  ie why not create a set of

I've got actually two reasons why I don't want to change the sources:

1) The sources of legacy applications would have to be changed to
   support them with my test harness, which I'd rather not require.
   But even in new applications it wouldn't help making the
   application code more readable.

2) In C++ it's sometimes hard to know and specify what functions are
   really called (overloading, templates etc.) at the source level.

> Alternatively have you considered using the "--wrap SYMBOL" 
> switch that 
> is provided by the linker ?

Frankly I didn't know about that feature in ld.  It certainly looks
very useful but I'd rather not commit to a single linker.  For
instance Microsoft's link.exe is much more often used around here and
I don't see anything similar in its docs.

> This would be difficult.  If the called function is in the same 
> compilation unit as the caller, then the compiler may have inlined it 
> automatically, even if it does not have the "inline" 
> qualifier.  It this 
> case you are hosed.  Even if the function is not inlined, the 
> call to it 
> can be computed statically by the assembler, so there may not 
> be a reloc 
> to tell the linker where the call originates or what is being called.
> 
> Now it is true that you could analyze all of the instructions in the 
> input object files, locate all call-subroutine instructions, 
> check their 
> destinations, and if any of them point to the start of one of the 
> functions you want to intercept then replace the destination address. 
> This would be time consuming and complex but it certainly can 
> be done. 
> (This approach would probably be best done as a separate tool 
> that runs 
> post-link.  It would not have to use libbfd unless you really 
> want to).
> 
> > 2) Can I use libbfd to determine if the interesting functions are
> >    inlined within the object under test (e.g. to issue an error
> >    message and require a recompilation with no inlining)?
> 
> No. :-(  Even if a function is inlined, its code (and name) 
> may still be 
> present in the object file.  This is usually selectable by a compiler 
> switch.
> 
> Note - there is a GCC patch available which records the 
> switches used to 
> build an object file as an extra section inside the object 
> file.  Thus 
> you could in theory scan this section and look for -finline or -O3 or 
> some other dangerous switch and issue an error message that way.  The 
> patch has not been accepted into the GCC sources yet though, 
> but you can 
> find it documented here:
> 
> http://gcc.gnu.org/wiki/Record%20GCC%20command%20line%20switch
> es%20in%20object%20files
> 
> >    Is it
> >    certain that all calls to the same function within a single
> >    compilation unit are either inlined or not (this is more of a
> >    compiler question, I guess)?
> 
> It is a compiler question and the answer is "no".  Calls via function 
> pointers for example cannot be inlined.  There are probably 
> other cases 
> as well, although I cannot think of any off the top of my head.

Again, thanks a lot that you have taken the time to explain all this
to me.  This actually leads me to the insight that I should simply
advice the user to compile her code with inlining turned off (gcc as
well as cl.exe support this and these are currently my primary
concern).

What I'd like to provide is a framework for easy generation of mock
objects and stubs.  I imagine the following steps, please feel free to
comment on them (believe me, I really need advice on that).

In a first step the user specifies the class under test (or rather
unit under test) as an object file together with the libs she isn't
intersted in mocking (like runtime libs etc.).  The test tool gathers
all undefined symbols, demangles their names (so C++ only) and
provides stubs to satisfy these symbols together with a framework to
specify expectations and to enforce those (like what parameters are
used, calling sequences and other things that other mock frameworks
support).  By reading the source code of nm I believe bfd provides the
needed support (besides demangling, because I'd need more structured
information than only a human readable equivalent of the mangled
symbol).

In a further step it would be nice to be able to also mock functions
defined within the unit under test.  Inlining issues aside, I could
imagine the following:

The user specifies the function she is interested in, the tool finds
the function's code in the object file and patches it with, say, a jmp
to an externally defined symbol (as its first instruction).  If this
is possible and when so, how, is currently completely beyond me.
Following some issues I can currently think of (please tell me which
others you can see):

1) Is it possible to inject imported symbols into an existing object
   file?  If so, how?

2) Obvious portability issues aside, can I easily find a functions
   code and patch it (in an existing object file)?  If so, how?

3) The goal of the patched in jump would have to deal with different
   calling conventions.  When the goal of the jump has the same
   calling convention as the the mocked function, I currently only see
   a problem with microsoft's thiscall convention (this ptr in CX).
   This would probably need special treatment (like inline assembly).
   Do you know of examples where a thiscall is 'transparently'
   transformed into a cdecl call or something?


TIA,

aa

-- 
Andreas Ames | Programmer | Comergo GmbH |
Voice:  +49 69 7505 3213 | ames AT avaya . com



More information about the Binutils mailing list