tags:

views:

401

answers:

4

I'm trying to write some small tests for a fairly small part of a fairly large project. Attempting to link this beast is unfortunately fairly impossible without linking the entire project together, which I don't want to do (it's a pretty complex system for finding all the dependencies and stuff, and I perfer not to meddle with it).

Now, I know for certain that the functions that the referenced functions won't be called during my test, the just happen to be part of functions which share file with stuff that I do test.

Is there any way to simply link these unresolved references to, let's say, abort, or something? Or is there a tool which creates the appropriate stub object file where all calls result in abort, given the set of object files that I have?

I use gcc (g++) for compiling/linking, version 3.4.4. Platform is unix (solaris/sparc if that's important).

+1  A: 

Well one way I can think of is to first compile the .o files for you library.

Then use a tool like nm (common on *nix systems) to get all of the symbols, in nm, all "external" (aka ones which are not found in this .o) are of type U (it may be different for non-GNU versions of nm see your documentation).

If your library is all one source file, then it is simple, pretty much all symbols of type U will be either a function found in another library or will be unresolved at link time. It is slightly more complicated if your library is going to be more than one source file since you will have inter-source file dependencies.

So now you have a a means to create a potential list of unresolved externals, then you can create a "test_stub.c" which has a stub symbols for each one, which you could fill with something like this:

void some_func() { abort(); }

where some_func is a would be unresolved external. Compile and link this with your library and all calls should result in an abort.

Evan Teran
cool trick, it's unfortunately far from a single .o-file, so it takes a bit of work... but i suppose nothing a bit of scripting won't solve.
roe
yea, i little greping should be able to go a long way. Would be very easy if all of your library functions have some common naming convention to let you separate out libc references.
Evan Teran
it's c++ unfortunately (name-mangling ftw!) :( do you know if there's a way to link objects into a single object? (kind of like ar I suppose, but I guess nm wont work on .a files?)
roe
well for name mangling do `nm -C` that'll give you demangled names. You can definitely link all .o files into a single one with `ld`, I forget the magic incantation though ;-). Once I am in front of my linux box I'll follow up.
Evan Teran
For C++ you could just link your objects with a file full of extern "C" functions with *mangled* names. The real problem is in external symbols from libraries that will be satisfied by linking process, so you'll have to ǒnsider the whole dependency tree of your system libraries.
Pavel Shved
A: 

Trying to compile the following program

#include <iostream>

extern int bar();

int foo()
{
  return bar() + 3;
}

int main()
{
  std::cout << "Hello, world!" << std::endl;
  // std::cout << foo() << std::endl;

  return 0;
}

results in

$ g++ -o main main.cc
/tmp/ccyvuYPK.o: In function `foo()':
main.cc:(.text+0x5): undefined reference to `bar()'
collect2: ld returned 1 exit status

But we can tell the linker to ignore unresolved symbols and run it just fine:

$ g++ -Wl,--unresolved-symbols=ignore-all -o main main.cc
$ ./main
Hello, world!

Say some unresolved function is called by your test harness (simulate this by uncommenting the call to foo), it will compile and link fine, but you'll get a segfault when you execute the program. Be sure to ulimit -c unlimited so you get a core.

Greg Bacon
+10  A: 

You can just tell linker to ignore unresolved symbols. I couldn't find option that links them to abort or something like that.

The policy to ignore unresolved symbols in object files only is the most natural, I suppose:

gcc -Wl,--unresolved-symbols=ignore-in-object-files  obj.o another.o etc.o

Other options include (quoting man ld):

   --unresolved-symbols=method
       Determine how to handle unresolved symbols.  There are four possi-
       ble values for method:

       ignore-all
           Do not report any unresolved symbols.

       report-all
           Report all unresolved symbols.  This is the default.

       ignore-in-object-files
           Report  unresolved  symbols  that  are  contained  in   shared
           libraries,  but  ignore  them if they come from regular object
           files.

       ignore-in-shared-libs
           Report unresolved symbols that come from regular object files,
           but  ignore them if they come from shared libraries.  This can
           be useful when creating a dynamic binary and it is known  that
           all  the  shared  libraries  that it should be referencing are
           included on the linker's command line.

       The behaviour for shared libraries on their own can also  be  con-
       trolled by the --[no-]allow-shlib-undefined option.

       Normally  the  linker  will  generate  an  error  message for each
       reported unresolved symbol but the  option  --warn-unresolved-sym-
       bols can change this to a warning.

On my Linux system attempts to call the unresolved function result in "Segmentation fault".

Pavel Shved
segmantation fault will do I suppose... :) thanks, I'll try the --warn-unresolved-symbols as well
roe
Cool. This is good information.
Mark Wilkins
the --warn-unresolved-symbols is perfect for me, that way I'll (hopefully) also notice if there's something that shouldn't be unresolved.
roe
A: 

Try GCC alias attribute:

/* cannot directly alias to yet undefined symbols,
 * so need an intermediate function.
 */
static void do_abort() { abort(); }

void func0() __attribute__ ((weak, alias ("do_abort")));
void func1() __attribute__ ((weak, alias ("do_abort")));
...
Nikolai N Fetissov