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).
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".
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.
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.
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")));
...
Related
There are a lot of questions about this on the web but I couldn't solve my problem. I've been studying this for a few days.
I want run a simple C++ class on Swift project, to this I followed this tutorial: http://www.swiftprogrammer.info/swift_call_cpp.html.
Basically I've followed the steps:
Create junk.cpp and junk.h files
Compile using g++ or/and clang++
Create .a file with: $ ar r libjunkcpp.a junk.o
ranlib libjunkcpp.a
Linked to Xcode in Build Phases -> Link Binary With Libraries -> Add
When I compiles, the follow errors occurs:
Undefined symbols for architecture x86_64:
"A::getInt()", referenced from:
_getIntFromCPP in wrapper.o
"A::A(int)", referenced from:
_getIntFromCPP in wrapper.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
junk.h
class A {
public:
A(int);
int getInt();
private:
int m_Int;
};
junk.cpp
#include "junk.h"
A::A(int _i) : m_Int(_i) {}
int A::getInt() {
return m_Int
}
wrapper.cpp
#include "junk.h"
extern "C" int getIntFromCPP() {
// Create an instance of A, defined in
// the library, and call getInt() on it:
return A(1234).getInt();
}
bridge.h
int getIntFromCPP();
This is an issue that sometimes occurs when using C or C++ libraries that get bridged through Objective-C into Swift. The issue isn't with how the Archive (static library) is built -- rather, it's a problem with an overly-aggressive linker creating the application.
The problem is that the linker sees the binding symbols and the C++ symbols, but never sees it being called from anywhere because it is actually invoked from a different language (Swift). This ultimately results in the linker aggressively stripping all symbols that it doesn't believe are being used in an effort to save space, which effectively removes all of the C++ code.
When this happens, nm will report the correct symbols as existing in the archive, but the actual application will fail to execute due to the symbols not being found.
As for solutions, there are actually several questions/answers already on Stack Overflow that address this issue in varying degrees:
How to disable C++ dead code stripping in xcode, where the solution is to use the linker flag -force_load to force that the static symbols are actually loaded.
Keeping Xcode from stripping out unused symbols from a static library which suggests using __attribute__((constructor)) to trick the linker into thinking the symbols are needed on construction, thus keeping them in.
Xcode Archive debug strip errors, which more broadly suggests toggling some Xcode configurations that may result in the symbols not being stripped. The suggestions in the answers here may conflict with the above two links, however.
It is difficult to provide a definitive and clear answer without more information on the existing setup, such as where wrapper.cpp is built, and how the bindings get used from within the Swift project. Given that this question is from 2018, I don't suspect there will be much more information on what this setup was at the time.
From the described symptoms, this sounds exactly like the issue my colleagues faced when doing C++/Swift bindings -- and the solution was ultimately to use -force_load which ensures that the archive is preserved in totality into the final application.
I am trying to build my program in OpenCL for ARM GPU - Mali.
I have a library libMali.so, which contains necessary symbols:
arm-v7a15v4r3-linux-gnueabi-nm *root_to_lib*/libMali.so
returns lines such as
002525b4 t clCreateKernel
and many others with all the expected OpenCL symbols.
However, compiling with
arm-v7a15v4r3-linux-gnueabi-g++ -c -Wall mandelbrot.cpp -o mandelbrot.o
arm-v7a15v4r3-linux-gnueabi-g++ mandelbrot.o -o mandelbrot -L*root_to_lib* -lMali
gives me errors like
mandelbrot.cpp:(.text+0x2e4): undefined reference toclCreateKernel'`
and others with all the symbols, which are actually present in libMali.so!
So, I kept the correct order of librabies in linking command, library is on the specified path (it is indeed) and it has the symbols.
Mangling is not the issue in this case as well: extern C specifiers were used in place and you can see that the raw entries of both lib and object file are not mangled.
Trying to accomplish the same thing using the arm-v7a15v4r3-linux-gnueabi-gcc didn't bring any change apart from necessity to link more c++ libs by hand (with -L*path* -llib).
libMali.so was built with arm-v7a15v4r3-linux-gnueabi-g++/gcc/ld, so this is not the matter of toolchain version.
I've ran out of ideas. May be someone here knows more tricky parts of linking process?
EDIT:
In fact, mandelbrot.cpp is a sample code from Mali-SDK. I'm just showing my linker problem on this example, since there obviously are no problems in the code. You can see the code here:
http://malideveloper.arm.com/downloads/deved/tutorial/SDK/opencl/mandelbrot_8cpp_source.html
http://malideveloper.arm.com/downloads/deved/tutorial/SDK/opencl/mandelbrot_8cl_source.html
If you look closely at the nm output:
002525b4 t clCreateKernel
you'll notice that the symbol is marked with a lowercase 't' which indicates that the symbol has a local binding (for example a static function) so it's not considered for binding to a undefined symbol in another object file. You can find an explanation of most of the cryptic "symbol type" letters used by nm here: https://sourceware.org/binutils/docs/binutils/nm.html
The readelf utility's output is more clear about symbols types.
Maybe the library was built incorrectly?
I am facing a unique problem as part of our application migration from HP to AIX.
The following simulated code produces different results in HP and AIX.
library.C **
#include <stdio.h>
#include "mylib.h"
int libimgclientFNXXX()
{
int check = 100;
check = FileNetDeleteDoc(check);
return check;
}
int libimgclientFN()
{
int check = 1;
printf("In lib ");
return check;
}
* main_func.C *
#include <stdio.h>
int libimgclientFN();
int libimgclientFNXXX();
int main()
{
int one = 0;
if (1 == 1)
{
one = libimgclientFN();
}
printf("\n The status is %d \n", one);
}
* mylib.h **
extern int FileNetDeleteDoc (int);
Note that the function libimgclientFNXXX() is never called.
My make file is as below:
xlC -c -g library.C -o library.o -I./
xlC -G -qmkshrobj -o libImgClient.so library.o
xlC -c -g -qpic=small main_func.C -o main_func.o
xlC -brtl main_func.o -L. -lImgClient -o TST
When I run TST, I get the following loading error
$ TST
exec(): 0509-036 Cannot load program TST because of the following errors:
rtld: 0712-001 Symbol FileNetDeleteDoc__Fi was referenced
from module ./libImgClient.so(), but a runtime definition
of the symbol was not found.
Even though the function libimgclientFNXXX() is never called, there is unresolved errors.
The exact same code built in HP works fine with no errors.
Any inputs is appreciated.
Thanks,
Yeah, "not using" a library function may still be an error, even if you are not going to call the code. It MAY defer the loading of some componanent until later, so it MAY not cause an error. Best not to have references to things that don't exist (or manually load the library and get the address, if the function doesn't exist, you'll get an error from the "find the function" call and you can do something sensible in the code).
The loader (the code that loads binary executables) isn't very clever, so it can't know exactly what is being called and what isn't. It's also possible that different compilers have different levels of cleverness for "dead code removal", so the one compiler completely removes the "never called" function, but another compiler doesn't remove it [because it's not got the cleverness to 100% certify that you never call the function - in gcc for example, it would know this if you made the libimgclientFNXXX a static function - because it knows that static functions don't get called outside this module, and this module isn't using it.
AIX requires all symbols to resolve at load-time, so even though it builds OK, because the symbol is referenced the applications will not run.
You need to use lazy linking for the .so (the -blazy link option), which should cause the missing function to be linked only on first use.
You really should not be leaving undefined symbols in a library, though - if it needs symbols from another library, you should be linking to them (unless it's a plug-in, where the symbol is exposed in the app itself).
In Solaris I have an exe file as per the guideline I need to add a shared library (.so) to extend the functionality. I have created a lthmyplugin.so file and added as described. Now the utlity run perfectly fine untill it calls my function After calling my function it fails.
Questions:
Is there any way to debug?
When I run the command truss it identifies aa.so
Also ldd -d lthmyplugin.so show no error except
symbol not found: __1cIMyPluginG__vtbl_ (./lthmyplugin.so)
symbol not found: __1cIThPluginG__vtbl_ (./lthmyplugin.so)
symbol not found: __1cOThLocalOptionsG__vtbl_ (./lthmyplugin.so)
symbol not found: __1cJThOptionsG__vtbl_ (./lthmyplugin.so)
Can this cause the programme to fail?
fyi, I have not used and any virtual function,constructors or destructors
What does this mean symbol not found: _1cIThPluginG_vtbl_ ?
Thanks,
You can use the nm tool to see the functions exposed by the so file. You can call:
nm -g lthmyplugin.so
... To see what functionality it exposes.
Besides that, given you've tagged this as C++, I'm going to take a stab and ask: did you specify a C style calling convention? If you didn't, it will mangle the names making them ugly, unreadable and in 99.9% of cases, unfindable. You can tell gcc not to mangle your functions by adding __attribute__((cdecl)), like so:
int not_mangled(int some_arg) __attribute__((cdecl))
{
return some_arg * 3;
}
I am writing a fairly large C++ shared-object library, and have run into a small issue that makes debugging a pain:
If I define a function/method in a header file, and forget to create a stub for it (during development), since I am building as a shared object library rather than an executable, no errors appear at compile-time telling me I have forgotten to implement that function. The only way I find out something is wrong is at runtime, when eventually an application linking against this library falls over with an 'undefined symbol' error.
I am looking for an easy way to check if I have all the symbols I need at compile time, perhaps something I can add to my Makefile.
One solution I did come up with is to run the compiled library through nm -C -U to get a demangled list of all undefined references. The problem is this also comes up with the list of all references that are in other libraries, such as GLibC, which of course will be linked against along with this library when the final application is put together. It would be possible to use the output of nm to grep through all my header files and see if any of the names corresponding.. but this seems insane. Surely this is not an uncommon issue and there is a better way of solving it?
Check out the linker option -z defs / --no-undefined. When creating a shared object, it will cause the link to fail if there are unresolved symbols.
If you are using gcc to invoke the linker, you'll use the compiler -Wl option to pass the option to the linker:
gcc -shared ... -Wl,-z,defs
As an example, consider the following file:
#include <stdio.h>
void forgot_to_define(FILE *fp);
void doit(const char *filename)
{
FILE *fp = fopen(filename, "r");
if (fp != NULL)
{
forgot_to_define(fp);
fclose(fp);
}
}
Now, if you build that into a shared object, it will succeed:
> gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed
succeeded
But if you add -z defs, the link will fail and tell you about your missing symbol:
> gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed
/tmp/cccIwwbn.o: In function `doit':
silly.c:(.text+0x2c): undefined reference to `forgot_to_define'
collect2: ld returned 1 exit status
failed
On Linux (which you appear to be using) ldd -r a.out should give you exactly the answer you are looking for.
UPDATE: a trivial way to create a.out against which to check:
echo "int main() { return 0; }" | g++ -xc++ - ./libMySharedLib.so
ldd -r ./a.out
What about a testsuite ? You create mock executables that link to the symbols you need. If the linking fails, it means that your library interface is incomplete.
I had the same problem once. I was developing a component model in C++, and, of course, components should load at runtime dynamically. Three solutions come to mind, that were the ones I applied:
Take some time to define a build system that is able to compile statically. You'll lose some time engineering it, but it will save you much time catching these annoying runtime errors.
Group your functions in well-known and well-understood sections, so that you can group of functions/stubs to be sure that each corresponding function has its stub. If you take the time on documenting it well, you can write perhaps a script that checks the definitions (via, for example, its doxygen comments) and check the corresponding .cpp file for it.
Do several test executables that load the same set of libraries and specify the RTLD_NOW flag to dlopen (if you're under *NIX). They will signal the missing symbols.
Hope that helps.