I have to make ELF file to use absolute paths for libraries instead of searching in default paths (RPATH).
This is result from readelf:
readelf -d example
Dynamic section at offset 0xe28 contains 24 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
But I want to get something like this:
readelf -d example
Dynamic section at offset 0xe28 contains 24 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [/lib/libc.so.6]
Are there any linker options to achieve this?
The tool you want is ldd, because those absolute paths are not part of the ELF file but are decided by the dynamic loader. ldd is a wrapper around environment variables that cause the dynamic loader to output the paths to the libraries that would be (or have been, depending on how you see it) loaded.
Of course, library resolution is a system-specific task and your results may vary across installs even of the same distribution.
AFAIK specifying the .so file as a normal input, using the absolute path, will result in a binary that also refers to the .so using that same absolute path.
Not sure how that works with default libs like libc, but you could try adding /lib/libc.so.6 as the first linker input.
Related
I have a program that statically links glib library and dynamically links a shared library that in turn also statically links the same glib library. When I run the program I get a segfault. After debugging in gdb I found that there is a global static variable defined in glib that's being set and it had different values in one call trace and than a later call trace. I then noticed that the variable addresses were different as well. So it seems like there are two copies of the global static variable? Shouldn't the executable override the symbol from shared library so there is only one global static variable in the executable during dynamic linking?
The other part of the story is that there is another executable that does the same as above, which seems to behave okay i.e., no segfault (haven't debugged to see if the different code paths load the same static variable). So perhaps this behavior is not deterministic.
The following issue is happening with gcc (8.3.1) on Linux (centos 7).
executableA (segfault) executableB (no segfault)
| \ | \
| (static) \(shared) |(static) \(shared)
| \ | \
libglib-2.0.a libA.so libglib-2.0.a libA.so
| |
| (static) |(static)
| |
libglib-2.0.a libglib-2.0.a
So it seems like there are two copies of the global static variable?
Yes, that is expected.
Shouldn't the executable override the symbol from shared library so there is only one global static variable in the executable during dynamic linking?
A static variable by definition has local linkage -- it is not accessible from any other compilation unit, and is not exported from the shared library(ies).
You would have to make this variable (and any other similar variables) non-static and exported from both shared libraries. Only then will the dynamic loader bind all references to this variable to a single instance.
Note that linking separate copies of libglib-2.0.a into shared libraries without controlling symbol visibility is asking for trouble. Whatever you hoped to achieve by doing that, you are not achieving.
there is another executable that does the same as above, which seems to behave okay
Ah, programming by coincidence. The mine you stepped on didn't explode, so it should be ok to continue doing that.
By default librtmp compile produces librtmp.so.1 file and symlink librtmp.so. I need to have librtmp.so without number suffix as andorid does not support it.
I was able to modify Makefile to get librtmp.so file:
#SO_VERSION=1
#SO_posix=.${SOX}.${SO_VERSION}
SO_posix=${SOX}
so the file produced file is now librtmp.so
But android can't load it as it still tries to load librtmp.so. (with dot):
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1891]: 170 could not load needed library 'librtmp.so.' for 'libffmpeg.so' (load_library[1093]: Library 'librtmp.so.' not found)
If a shared library has DT_SONAME dynamic tag of foobar.so.56, then no matter what you call the actual file (e.g. foo.so, or libbar.so), when you use that library to link an executable, the SONAME is recorded in the executable (as DT_NEEDED dynamic tag), and not the actual file name.
It follows that your librtmp.so has a DT_SONAME of librtmp.so.. You can confirm that with:
readelf -d librtmp.so | grep SONAME
So what do you need to do to get rid of SONAME? Get rid of -Wl,--soname=... somewhere in your Makefile.
how can i check executable if it uses SONAME or filename
The executable will always use SONAME (if present). You can check the libraries that executable needs by looking for DT_NEEDED tags in the executable's dynamic section:
readelf -d a.out | grep NEEDED
I have a question regarding an article of JNI at http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html.
gcc -o libnativelib.so -shared -Wl,-soname,libnative.so
-I/export/home/jdk1.2/include
-I/export/home/jdk1.2/include/linux nativelib.c
-static -lc
I guess I am still a little confused with the function of '-o libnativelib.so' and '-Wl,-soname,libnative.so'.
'-o libnativelib.so' specify the name of output file of gcc to be libnativelib.so. From what i understand it is the library name to load from JAVA side as shown in the article:
static {
System.loadLibrary("nativelib");
}
So what's the use of '-Wl,-soname,libnative.so'?
I found following info on ld option manual:
-soname=name
When creating an ELF shared object, set the internal DT_SONAME field to the specified name. When an executable is linked with a shared object which has a DT_SONAME field, then when the executable is run the dynamic linker will attempt to load the shared object specified by the DT_SONAME field rather than the using the file name given to the linker.
So what does it mean? When final executable is run, linker will attempt to load ?? rather than ?? in the name of ??
This is useful for a system, where one library can be present under several names, for example: libz.so, libz.so.1, libz.so.1.2.3. All these libraries are symlinks to one file, and DT_SONAME inside it points to "libz.so.1". When you link your code against libz.so, it will record dependency on "libz.so.1" in the executable file. And when your file is executed on another system, which contains, say, libz.so.1.2.5, it will still work, because it will look for libz.so.1. But if the destination system will have much newer version, like libz.2.3.4, it will fail, because libz.so.2, but not libz.so.1 will be present.
DT_SONAME field is used only by linker. When you use System.loadLibrary(), the file name is specified by you, and the value of this option is not used. If you want, you can implement a similar versioning scheme for you libnative, to ensure that you java code always load a compatible version.
From GCC-HOWTO:
Each library has a soname. When the linker finds one of these in a library it is searching, it embeds the soname into the binary instead of the actual filename it is looking at. At runtime, the dynamic loader will then search for a file with the name of the soname, not the library filename. Thus a library called libfoo.so could have a soname libbar.so, and all programs linked to it would look for libbar.so instead when they started.
In your case, the soname libnative.so is different from the file name libnativelib.so.
You'll have to symlink libnative.so to libnativelib.so to allow the dynamic loader to find the shared lib.
Say I am creating an application bundle with some scripts, maybe a daemon, or even a helper binary... When compiling such a binary.. is it feasible to ./configure/make it with only relative paths? For example, a more conscientious Makefile will include for provisions such as...
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--datadir=DIR read-only architecture-independent data [DATAROOTDIR]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/hiawatha]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
--psdir=DIR ps documentation [DOCDIR]
This is great, you can install everything to /opt/local instead of /usr/local. Maybe even go crazy, and rename the binaries via sed.. I get it..
But what remains unclear in my tiny brain, is if the ability to arbitrarily set paths in such a manner extends to the ability to map the directories relative to the executable, in a manner similar to...
--prefix=PREFIX install architecture-independent files in PREFIX [/usr/local]
--prefix=./ aka [../relative/to/binary]
So, for example, no matter where you launched the bin from, it would always know that it's .conf file was going to be up one folder, in the that relative ../etc folder, or possibly even right next to it, in the same directory, ./. Similarly, you could guarantee write access to log and pid files, etc, without wondering about your target's permissions/directory structure...
This would enable a completely portable /bin /etc /lib /var directory structure, within a PATH to which I can guarantee some semblance of predictability... but I don't think it just "works" like that.. And I am unsure if simply "linking statically" or otherwise ? truly creates binaries that are able to be moved to another system (albeit, for this scenario, to ones with the same support libs in the same places, so as not to muddle the issue) Is it possibly to cross-compile in this manner? And can you build for multiple architectures in the same build cycle? (For example i386 AND x86_64 at the same time)
Maybe I could just use a recommendation of a good GNU/GCC primer ( CC, CFLAGS, LDFLAGS, -l, , -I , and CPP 101, etc.) but that wasn't written for (and by) Math teachers - in the 70's?
In full generality, no, that won't work. There are things in /etc for example that are expected to be shared by the whole system and won't work correctly if you're trying to keep a private copy for one app.
With that said, your app probably isn't using every single shared resource on the system. Either using a local /bin and /sbin, or symlinking to the real ones from a relative path within your app's directory should be fine. /var seems less likely as something that your app needs to know about directly - anything stopping you from storing logs your own way, or using syslogd?
Hey, I just Downloaded openvrml from macports
(port install openvrml)
Now I have a Sample program (pretty_print.cpp from openvrml at sourceforge) that begins like this:
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
# include <openvrml/vrml97_grammar.h>
# include <openvrml/browser.h>
# include <fstream>
...
then in Xcode, I added the following path and check "recursive" for the Header search path and Lib Search Path:
/opt/local/var/macports/software
And all '***.h file not found' errors disappeared, but now I have the following two:
complex.h 943 '__pow_helper' is not a member of std
c++locale.h 71 'vsnprintf' is not a member of std
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/complex: In function 'std::complex<_Tp> std::pow(const std::complex<_Tp>&, int)':
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/complex:943: error: '__pow_helper' is not a member of 'std'
both errors come from system files.
I wonder what is causing this errors...
Can anyone advice me on how to use openvrml samples on Macs?
thanks in advance.
I've had a similar problem. I defined "recursive" flag for an '/opt/local/include' path. This pulled in some strange c++ headers from boost compatiblity includes.
In general, you do not want "recursive" flag on your include paths.
Try unchecking "recursive" from your paths.
if you put recursive on a path containing boost headers you'll use some random boost headers, which are likely designed to be used in different environment and/or different compiler, instead of standard C++ headers, meaning, for example, you'll include TR1 header instead of standard header. This is likely to be the cause of your problem (it happened to me too).
Just locate the directory which contains the headers you need and put only that in header search path instead of being lazy and using "recursive" flag, since there are a lot of header files which have same name but differ in location only.