Linux find undefined symbol

Linux: C++ lookup error – undefined symbol

At a customer site, we had a C++ program (renamed for the purpose of this blog to myprogram) which was failing after running for some time. It’s a program processing messages from an external system and seemed to fail only when the processing of the message triggered some given operations. The error message was:

lookup error: /home/xxx/bin/xxx/myprogram: undefined symbol: _Z22CxxxPxxxExxxPxxxR6CDBManRKSsRSt6vectorISsSaISsEE

The first thought was to use ldd to check whether everything was fine:

# ldd myprogram linux-gate.so.1 => (0xffffe000) libxxx230.so => not found libmc3adv.so => not found libsybdb.so => not found libxxxutl.so => not found libxxxdb.so => not found libxxxcustom.so => not found libxerces-c.so.23 => not found libdl.so.2 => /lib/libdl.so.2 (0x4001e000) libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x40022000) libm.so.6 => /lib/tls/libm.so.6 (0x400df000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x40101000) libc.so.6 => /lib/tls/libc.so.6 (0x40109000) /lib/ld-linux.so.2 (0x40000000)

So many not found ! Ok I must have forgotten something… Of course, LD_LIBRARY_PATH is probably not set in my shell:

# pidof myprogram 10132 # export `cat /proc/10132/environ | strings | grep LD_LIBRARY_PATH`
  • pidof return the id of the process running the specified program
  • /proc/10132/environ contains the whole environment of the specified process
  • strings is required to convert the 0x00 separated strings of /proc/xxx/environ
  • The rest just gets the line LD_LIBRARY_PATH=… and uses export to set it in my shell as well

Now I have the same LD_LIBRARY_PATH as the process running myprogram and can rerun ldd:

ldd myprogram linux-gate.so.1 => (0xffffe000) libxxx230.so => /home/xxx/libs/libxxx230.so (0x40018000) libmc3adv.so => /home/xxx/libs/libmc3adv.so (0x40051000) libsybdb.so => /opt/sybase-12.5/OCS-12_5/lib/libsybdb.so (0x403a5000) libxxxutl.so => /home/xxx/libs/libxxxutl.so (0x404e1000) libxxxdb.so => /home/xxx/libs/libxxxdb.so (0x405c5000) libxxxcustom.so => /home/xxx/libs/libxxxcustom.so (0x4068d000) libxerces-c.so.23 => /home/xxx/libs/libxerces-c.so.23 (0x40695000) libdl.so.2 => /lib/libdl.so.2 (0x40985000) libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x40988000) libm.so.6 => /lib/tls/libm.so.6 (0x40a46000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x40a68000) libc.so.6 => /lib/tls/libc.so.6 (0x40a70000) libstdc++-libc6.1-1.so.2 => /usr/lib/libstdc++-libc6.1-1.so.2 (0x40b8a000) libpthread.so.0 => /lib/tls/libpthread.so.0 (0x40bd2000) /lib/ld-linux.so.2 (0x40000000)

Everything looks OK. So it’s not that a library is missing. Also the paths to the libraries are OK.

Executing ldd -r -d myprogram basically just shows me the same plus an error with the missing symbol.

Finally, comparing the size of the library files on this system and at another customer site with the exact same version of the software gave us the answer: somehow a different version of one of our library landed there and didn’t contain the missing symbol.

So the search ended there. Otherwise we’d have had to use the following:

Use c++filt to find out the method behind the mangled symbol name:

# c++filt _Z22CxxxPxxxExxxPxxxR6CDBManRKSsRSt6vectorISsSaISsEE CxxxPxxxExxxPxxx(CDBMan&, std::basic_string, std::allocator > const&, std::vector, std::allocator > >&)

Use nm to list the symbols in the libraries shown by ldd:

This will show the mangled symbol names. For demangled symbols, use the -C option:

# nm -C /home/xxx/libs/libxxxdb.so

Источник

How do I find where a symbol is defined among static libraries

Suppose you work with a codebase comprising several tools and libraries and you want to port (or resurrect) some component within such codebase but any clue about where symbols lie within the various libs is either lost or will take ages to find out by looking at the code itself (yes improved documentation can avoid such issues but is quite demanding). What is the fastest way to discover in which library you can find symbols used in the code?

3 Answers 3

Assuming a linux box, the nm tool, listing names in library files, comes to the rescue.

It can be used to do an extensive search as follows: one can first find all the libraries available (assuming the project have been successfully compiled without the component you are adding) with a find, then such find can be enclosed in a loop where you call nm on all discovered libraries; the output you then grep for discarding «U» references (undefined symbols, aka where else the symbol is being used). On a single bash line that gives:

for lib in $(find base_path -name \*.a) ; do echo $lib ; nm $lib | grep my_symbol | grep -v " U " ; done 

The echo generates a list of all libraries found, which is not so clean since it outputs names of libs not holding the symbol, but it was the fastest way I found to have a direct reference to the library so when you see a:

base_path/component/libA.a 0000000000000080 D my_symbol 

You have found your usual suspect.

Источник

Linux shared library that uses a shared library undefined symbol

two shared libraries liba.so and libb.so. liba.so uses libb.so. All c files are compiled with -fPIC. Linking uses -shared. When we call dlopen on liba.so it cannot find symbols in libb.so. we get the «undefined symbol» error. We can dlopen libb.so with no errors. We know that liba is finding libb because we don’t get a file not found error. We get a file not found error when we delete libb.so. We tried -lutil and no luck. Any ideas. oh yeah. gcc 4.1.2 update: We use rpath when linking liba so it can find libb. ldd liba.so returns:

linux-gate.so.1 => (0xffffe000) libb.so => ./libb.so (0xf6ef9000) /lib/libutil.so.1 (0xf6ef5000) libdl.so.2 => /lib/libdl.so.2 (0xf6ef1000) libm.so.6 => /lib/libm.so.6 (0xf6ec9000) libpthread.so.0 => /lib/libpthread.so.0 (0xf6eb1000) librt.so.1 => /lib/librt.so.1 (0xf6ea8000) libc.so.6 => /lib/libc.so.6 (0xf6d62000) /lib/ld-linux.so.2 (0x007d0000) 

You are saying: you created two libs (-fPIC -shared), liba.so and libb.so. liba.so is dinamically linked (or it should be. ) with libb.so and uses it. In a program X you try dlopen on libb.so and everything is ok; another test program Y tries to dlopen liba.so but it fails, nonetheless you know liba.so finds libb.so correctly since you tried to delete libb.so and another issue is raised. options you’re using for dlopen?

You got it all right. Right now we use no options, because dlopen is called from some program we have no control over.

ldd says libb.so => ./libb.so (0xf6ef9000) among other things. All the other lines have an extra .# after the so name, like «libutil.so.1 => /lib/libutil.so.1 (0xf6ef5000).» Is it significat that there is no .# after libb.so.

2 Answers 2

You can easily check where libb.so is expected to be with ldd command:

 $ ldd liba.so linux-gate.so.1 => (0xb77b0000) libb.so.1 => not found libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb75b6000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7572000) libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb742b000) /lib/ld-linux.so.2 (0xb77b1000) 

If it’s not found , libb.so ‘s path should be added to /etc/ld.so.conf or shell variable LD_LIBRARY_PATH .

Another way is setting rpath in the liba.so itself — it’s basically hardcoding its path so when the binary is started the dynamic linker would know where to search for the shared libraries.

If rpath is not set it will first search in LD_LIBRARY_PATH , then the paths mentioned in /etc/ld.so.conf (or /etc/ld.so.conf.d/). After adding to ls.so.conf don’t forget to execute /sbin/ldconfig

Dynamic linker searches the dependent shared libraries by their soname (if it’s set) — if soname is not set (with -Wl,-soname,libb.so.1 for example), it will be searched by library’s name.

Example: libb.so.1.0 is your actual library, having soname — libb.so.1 . You would normally have the following files structure:

libb.so -> libb.so.1 libb.so.1 -> libb.so.1.0 libb.so.1.0 

where libb.so and libb.so.1 are symlinks.

You usually link to libb.so , when building some application or other library, depending on libb.so .

gcc -shared -Wl,-soname,liba.so.1 -o liba.so.1.2 -L/libb/path -lb 

When the application is started (or dlopen is executed — your case) — the dynamic linker will search for file with name libb.so.1 — the soname of dependent library, if the soname is set, not libb.so .

That’s why you need that symlink libb.so.1 , pointing to the actual library.

If you use ld.so.conf and ldconfig , it will create the symlink with soname ‘s name, pointing to the library file, if this symlink is missing.

You can see ld-linux man page for more useful info.

If the library is found but some of the symbols are missing, try building libb.so with -Wl,—no-undefined option

gcc -shared -Wl,-soname,libb.so.1 -Wl,--no-undefined -o libb.so.1.2 

It should give you an error if you missed to define some symbol.

Источник

How to list all externally-undefined symbols of a static library on Linux?

So that I can find out all external symbol dependencies of this library.

2 Answers 2

ld -r -o deleteme.o --whole-archive libfoo.a nm -C --undefined-only deleteme.o # `-C` if you might have C++ archive members rm deleteme.o 
extern void two(void); void one()
extern void three(void); void two()

Make a static library libonetwo.a :

$ gcc -Wall -c one.c two.c $ ar rcs libonetwo.a one.o two.o 

nm parses the static library as if it were just a commandline list of its members:

$ nm --undefined-only libonetwo.a one.o: U _GLOBAL_OFFSET_TABLE_ U two two.o: U _GLOBAL_OFFSET_TABLE_ U three 

So incrementally link them all into a temporary object file:

$ ld -r -o deleteme.o --whole-archive libonetwo.a 

Then see the residual undefined symbols of that object file and delete it:

$ nm --undefined-only deleteme.o && rm deleteme.o U _GLOBAL_OFFSET_TABLE_ U three 

There is no single command (that I know of) that will do that.

But it’s trivial to construct two commands, one for all undefined, and one for all defined symbols, and then show only the difference between them.

First nm prints only defined symbols. Second nm prints only undefined symbols (which may be defined in another file in the same library).

The comm -13 prints only lines from second nm which do not occur in the output from the first nm .

Источник

symbol not found AKA undefined symbol

Most of the people who work on UNIX will face this irritating error often. and some times it will take less time to solve and sometimes it will take hell lot of time. Even i faced this regularly and i need some good document or an article regarding the specific error in c/c++ what are all the cases where there might be Symbol not found/Undefined Symbol error. Could anybody help me to know what are all those cases?

4 Answers 4

The error is not related to UNIX/Windows/any other OS, but rather to the languages themselves. It is actually rather simple to diagnose with the information that compilers provide. Usually they will tell you what symbol is missing and sometimes where it is being used. The main reasons for a symbol to be missing are:

  • You have declared but never defined it
  • You have defined it, but did not add the compiled symbol (object file/library) to the linker
  • It is external and you forgot to link the library, or you are linking an invalid version, or in the wrong order.

The first one is a little trickier if you intended to define the symbol but did not match the declaration (declared void foo( int, double ); , but defined void foo( double, int ) . As with all other cases, the compiler will tell you the exact signature that it is looking for, make sure that you have defined that symbol, and not something close or similar, a particular corner case can be if you are using different calling conventions in the declaration and the definition, as they will look very similar in code.

In the case of libraries external code the complexity is in identifying what library needs to be linked for that symbol to be added, and that comes from the documentation of the lib. Beware that with static libraries the order of the libs in the linker command line affects the result.

To help you in finding what symbols are actually defined you can use nm (gcc, which is common among unix systems). So basically you can run nm against the object files/libs that you are linking and search for the symbol that the linker is complaining about. This will help in cases where the order is what makes the difference (i.e. the symbol is there, but the linker skipped it).

At runtime (thanks to Matthieu M. for pointing it out) you might have similar issues with dynamic libraries, if the wrong version of a library is found in the LD_LIBRARY_PATH you might end up with a library that does not have a required symbol.

Источник

Читайте также:  Python среда разработки линукс
Оцените статью
Adblock
detector