objdump/nm for libtool object (.lo) files - compilation

I compiled an open source library and it turned out that there are unresolved symbols within the generated shared library (.so). The natural next step seemed to me finding out which object has the unresolved symbols, but I could not apply nm or objdump to the intermediate libtool object files (.lo). Is there any way I can take a look at the list of symbols within .lo files?

You need to run nm or objdump on the object files (.o files), not the .lo files. The .lo files are used by libtool and are text files that can tell you where your object files really are:
# Name of the PIC object.
pic_object='.libs/libfoo_la-foo.o'
# Name of the non-PIC object
non_pic_object='libfoo_la-foo.o'
Since you need to know about a DSO (the .so file), the pic_object files are probably the ones you want to examine.

Related

gcc archives not considered when linking?

Should it make a difference whether a gcc linker links archive files or object files (or both)?
Background:
In an embedded project, an ISR (which is of course not referenced by any other source code) is located as the only function in a file. This file is compiled to an object file and then put into an archive file.
Other functions in other files are compiled to separate object files.
The binary is built without complaints and runs on the target with no exceptions, no matter whether the linker uses the ISR object file or the ISR archive file.
However, if using the archive file, the ISR is not linked.
Plus, if there is any other reference (e.g. a variable used by some other function in some other file) in the same file, it is linked completely.
Why this?
Yes, it makes a difference.
Any object file that is specified on the linker commandline is linked
into the executable, regardless of whether any of the symbols that it
defines are referenced by the executable.
The linkage of a static library is different. It is an archive of object
files. For each object file in the archive, the linker will determine
whether that object file provides a definition for any of the symbols
that are so far undefined at that point in the linkage. If it does so,
then the linker will extract that object file from the archive and
link it in the executable; otherwise not.
This behaviour is as documented for the ld, the GNU linker {- l | --library }
option:
-l namespec
--library=namespec
...
The linker will search an archive only once, at the location where
it is specified on the command line. If the archive defines a symbol
which was undefined in some object which appeared before the archive
on the command line, the linker will include the appropriate file(s)
from the archive. However, an undefined symbol in an object appearing
later on the command line will not cause the linker to search the
archive again.
...
(To see that this applies to linkages invoked with gcc or another GNU compiler,you may need to know that the named compiler is simply a tool-driver that delegates to the appropriate tool for discharging the commandline options that are presented: when it sees options that call for a linkage, it calls ld.)
Hence the object file containing the unreferenced ISR is not linked when
it is in a library, and contains no other referenced symbols, and it is
linked when it is not in a library, or when it contains some other
referenced symbol.

Link multiple object files in gfortran

I have "library" folder with multiple object (.o) files. These files contain subroutines which are not changing from project to project. Each new project uses some of those object files, but not all of them.
Could you please tell me is there any way to tell gfortran to look up that folder for necessary .o files?
I've tried -I and -L options, but no way. When I write .o names directly, it works:gfortran main.for ./library/obj1.o ./library/obj2.o but I have many of .o files and write all of them waste time.
I could write gfortran main.for ./*.o but then main program will be linked with all .o files, but it needs only some of them.
I hoped that something like gfortran main.for -L./library/ will work, but it doesn't.
I use OS X with gcc version 5.1.0.
And I'm pretty sure that I should use makefile for such case
You are confusing object files with static libraries. An object file
is not a static library and the gfortran linker - which is simply
the GNU system linker, invoked by gfortran - will not treat it as such.
You need a static library and you are trying to use object files in lieu.
The linker recognizes an object file by the extension .o. It recognizes
a static library by the extension .a, and it expects the contents of an .a file
to have the form of a static library, not the format of an object file. (So you
cannot make an object file into a static library just by renaming it).
The linker will link into your program every object file that appears on its
commandline, whether or not it is needed. It does not expect you to mention
object files if you don't want them linked. The linker options -L and -l for
locating libraries have no application to object files.
A static library is a fairly simple archive containing some number of
object files, plus a house-keeping header and typically an index of the
public symbols defined in the contained object files.
When the linker encounters a static library on its commandline, it does not
link the entire contents of the library (unless you expressly tell it to). It inspects
the contained object files to determine which, if any, of them contain
definitions for symbols that are as yet undefined at that point in the linkage
of the program. If any object file in the library is found to provide any
of the missing definitions, then that object file is extracted from the library
and linked into the program. Object files in the library that provide no
missing definitions are not linked. Libraries on the commandline are sequentially
inspected in this way until either all the symbols referred to by the program
have definitions in linked object files or there are no more libraries.
If as you say the object files that you are trying to use as libraries are stable
resources that you never have to build for your projects, then you can just make a static
library out of them and link that library with your per-project programs.
To make a static library from object files, use the ar tool.
See man ar.
When you have made your library, say, libsubs.a, and have decided it shall reside
in some directory, /path/to/subs, then you link it with a program by adding
-L/path/to/subs -lsubs
to the commandline in which your program is linked. This will cause the linker
to search for a library called libsubs.a in directory /path/to/subs.
So if you are compiling and linking in a single step, use it like:
gfortran -o myprog myprog.f90 -L/path/to/subs -lsubs
And if you are compiling and linking in distinct steps, use it like:
gfortran -c -o myprog_1st_file.o myprog_1st_file.f90
gfortran -c -o myprog_2nd_file.o myprog_2nd_file.f90
gfortran -o myprog myprog_1st_file.o myprog_2nd_file.o -L/path/to/subs -lsubs
This is how you are supposed to use a set of object file resources of which
different subsets will be required for linkage with different programs: you put
them in a library and link the library.

Linking .a files in Mac OSx

I have added libxxx.a in /usr/lib but when I perform otool -L myproject.so, libxxx.a was not included in the list of libraries. I have also included libxxx.a in my build file so I was thinking that I have successfully added it.
How can I like .a file?
I didn't have a problem with .dylib files though.
otool won't show the static library as they are included within the executable binary (a .dylib in this case). This is because static libraries are a collection of object (.o) files and it's pretty much the same as adding file1.o ... fileN.o to the linker command line and you can't see object files from otool either.
One way to check that your static library is part of the executable (other than it successfully linking) is to use the nm command which lists symbols. Providing the executable binary is not stripped, you would do something like:
$ nm /path/to/libLibrary.dylib | grep aClassOrFunctionInStaticLibrary
and the symbol being searched should have the letter t next to it, to indicate that it's part of the executable text section.
Also as mentioned by #PaulR, /usr/lib is part of the operating system and you should not add files there; use /usr/local/lib instead as /usr/local is designed for site-specific additions to the system and files there will survive an operating system update.

glibc version used while building .a file

Is there a way to find out from .a file what version of glibc is expected or was used when building the .a?
It's not a meaningful question about an ar file or a .o file. All they record is naked symbol names. When you make a shared object or an executable, the linker gives you symbols references like time##GLIBC_2.2.5 for the undefined symbols.

Questions on GCC linker

Apologize because for the moment I don't have the environment to experiment and sort out the following questions myself:
1) Let's say I have four library files: libmylib_super.a and libmylib_super.so, mylib_dumb.a and mylib_dumb.so. While specifying libraries to link to, what are the differences between the following approaches:
A) -l:libmylib_super.a
B) -llibmylib_super
C) -lmylib_super
D) -lmylib_dumb
2) Definition of -static from man page:
On systems that support dynamic
linking, this prevents linking with
the shared libraries. On other
systems, this option has no effect.
Does this linker option have anything to do with question #1? Or... by any chance will they interfere with each other?
Thanks.
--- edited 2009-12-28 ---
I just got my environment up and experimenting a bit, by linking to Boost date_time library. Say I have three library files: libboost_date_time-mt-d.a, libboost_date_time-mt-d.so.1.41.0, libboost_date_time-mt-d.so -> libboost_date_time-mt-d.so.1.41.0 (sym link).
A.1) -l:libboost_date_time-mt-d.a ==> linking OK, binary works even without the library file.
A.2) -l:libboost_date_time-mt-d.a with -static ==> linking error /usr/bin/ld: cannot find -lm
C.1) -lboost_date_time-mt-d ==> linking OK, binary works but requires the shared library file.
C.2) -lboost_date_time-mt-d with -static ==> linking error /usr/bin/ld: cannot find -lm
Any idea about the error in A.2 and C.2?
Additionally, while running the program in C.1, it seems searching the shared library file with name libboost_date_time-mt-d.so.1.41.0 but not the libboost_date_time-mt-d.so. Wouldn't that be inconvenient if the program is running on a system without the exact version of library? What could be the practical way to handle the version while using shared library?
According to the manual,
A) searches the library path for a file exactly named libmylib_super.a (the search first for a shared library behavior doesn't apply)
B) searches the library path for a file named liblibmylib_super.so first then liblibmylib_super.a or only searches for a file named liblibmylib_super.a if -static is used -- note it's the linker that adds the lib prefix and the file extension
C) searches the library path for a file named libmylib_super.so first then libmylib_super.a or only searches for a file named liblibmylib_super.so if -static is used
D) see C)
Note that B) won't work because it's the linker that should add the lib prefix to the library name.
Note that D) won't work because your mylib_dumb doesn't follow the naming convention.
See the GNU Linker Manual:
-l namespec
--library=namespec
Add the archive or object file specified by namespec to the list of files to link. This option may be used any number of times. If namespec is of the form :filename, ld will search the library path for a file called filename, otherwise it will search the library path for a file called libnamespec.a.
On systems which support shared libraries, ld may also search for files other than libnamespec.a. Specifically, on ELF and SunOS systems, ld will search a directory for a library called libnamespec.so before searching for one called libnamespec.a. (By convention, a .so extension indicates a shared library.) Note that this behavior does not apply to :filename, which always specifies a file called filename.
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.
See the -( option for a way to force the linker to search archives multiple times.
You may list the same archive multiple times on the command line.
This type of archive searching is standard for Unix linkers. However, if you are using ld on AIX, note that it is different from the behaviour of the AIX linker.

Resources