I am linking an so, that depends on libmxml.so. However I have no rights install libmxml.so.
So thats what I am doing
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o -L ../../../../system/addonlibs/ -lmxml -lpthread
ldd shows me
ldd ServiceProvider.so
libmxml.so.1 => not found
libpthread.so.0 => /lib/libpthread.so.0 (0x40026000)
libc.so.6 => /lib/libc.so.6 (0x40046000)
the second try was
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o ../../../../system/addonlibs/libmxml.so -lpthread
and still ldd shows me
ldd ServiceProvider.so
libmxml.so.1 => not found
libpthread.so.0 => /lib/libpthread.so.0 (0x40026000)
libc.so.6 => /lib/libc.so.6 (0x40046000)
Consequently, ldd does not find the library, since I only have "libmxml.so", but no "libmxml.so.1". How do I get rid of this ".1" suffix? Why is it comming?
When you link with a dynamic library, you should not do :
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o ../../../../system/addonlibs/libmxml.so -lpthread
Instead, make sure that /yourpath/system/addonlibs (you should use the full path instead of a relative one) is in you LIBRARY_PATH. Then change you link command.
export LIBRARY_PATH=/yourpath/system/addonlibs:$LIBRARY_PATH
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o -lmxml -lpthread
You can also write that:
gcc -shared -m32 -o ServiceProvider.so ServiceProvider.o -L/yourpath/system/addonlibs -lmxml -lpthread
However, to run your program, you will need to have your library path in LD_LIBRARY_PATH.
If you have issues with .soand .so.1 stuff, then rename your .so to .so.1 and make a symlink from .so.1 to .so.
Edit:
If you do objdump -p libmxml.so | grep SONAME you will probably get libmxml.so.1.
It is where you get the libmxml.so.1 identifier.
Related
I have an executable shared_main , a shared library libbar.so and a dynamic load shared library libfoo.so (load in shared_main via dlopen).
shared_main doesn't use any symbols from libbar.so but libfoo.so does.
So gcc -g -Wall -o shared_main shared_main.c libbar.so -ldl doesn't link libbar.so to shared_main.
Checked via ldd shared_main.
How to let gcc force shared_main link libbar.so?
P.S. I know I can link libfoo.so with libbar.so. But I want to try if I can force shared_main to link libbar.so here.
shared_main.c
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
int main(){
void* libHandle = dlopen("./libfoo.so", RTLD_LAZY);
if(libHandle == NULL){
printf("dlopen:%s", dlerror());
exit(1);
}
int(*xyz)(int);
xyz = (int(*)(int)) dlsym(libHandle, "xyz");
if(xyz == NULL){
printf("dlsym:%s", dlerror());
exit(1);
}
int b = xyz(3);
printf("xyz(3): %d\n", b);
}
foo.c (libfoo.so)
void func_in_bar();
int xyz(int b){
func_in_bar();
return b + 10;
}
bar.c (libbar.so)
//mimic python share library runtime
#include <stdio.h>
void func_in_bar(){
printf("I am a Function in bar\n");
}
void another_func_in_bar(){
printf("I am another function in bar\n");
}
makefile
shared_main:
gcc -g -Wall -o shared_main shared_main.c libbar.so -ldl
shared:
gcc -g -Wall -fPIC -shared -o libfoo.so foo.c
gcc -g -Wall -fPIC -shared -o libbar.so bar.c
You have an XY-problem, where X is: libfoo has unresolved symbols, but the linker doesn't warn about it
So use the -z defs option linkage-time, and when you get the linker error about the unresolved symbol add -lfoo to the linkage command.
That's still not enough, you will have to use a -L and a -Wl,-rpath option too. Here is a complete Makefile:
# Makefile
# LIBDIR should be the final place of the shared libraries
# such as /usr/local/lib or ~/libexec/myproject
LIBDIR := ${PWD}
TARGETS := shared_main libbar.so libfoo.so
all: ${TARGETS}
clean:
rm -f ${TARGETS} 2>/dev/null || true
shared_main: shared_main.c
gcc -g -Wall -o shared_main shared_main.c -ldl
libbar.so: bar.c
gcc -g -Wall -fPIC -shared -o libbar.so bar.c
libfoo.so: foo.c libbar.so
gcc -g -Wall -fPIC -shared -z defs -o libfoo.so foo.c \
-L${LIBDIR} -Wl,-rpath,${LIBDIR} -lbar
Edit: nonetheless, here is a hackish solution for the original question: use option -Wl,--no-as-needed
shared_main:
gcc -g -Wall -o shared_main shared_main.c \
-Wl,--no-as-needed -Wl,-rpath,${PWD} libbar.so -ldl
Everything works just fine for me, with unmodified files from OP.
$ make shared
gcc -g -Wall -fPIC -shared -o libfoo.so foo.c
gcc -g -Wall -fPIC -shared -o libbar.so bar.c
$ make shared_main
gcc -g -Wall -o shared_main shared_main.c libbar.so -ldl
$ LD_LIBRARY_PATH=. ldd shared_main
linux-vdso.so.1 (0x00007ffccb5f2000)
libbar.so => ./libbar.so (0x00007f78f6ce0000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f78f6cd1000)
libc.so.6 => /lib64/libc.so.6 (0x00007f78f6b06000)
/lib64/ld-linux-x86-64.so.2 (0x00007f78f6ce7000)
$ LD_LIBRARY_PATH=. ./shared_main
I am a Function in bar
xyz(3): 13
I only needed to help the library loader out a bit using LD_LIBRARY_PATH.
$ gcc --version
gcc (GCC) 11.3.1 20220421 (Red Hat 11.3.1-2)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ ld --version
GNU ld version 2.37-17.fc35
Copyright (C) 2021 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
The answer is -Wl,--no-as-needed.
For my example, the full command is:
gcc -g -Wall -o shared_main shared_main.c -Wl,--no-as-needed libbar.so -ldl
From https://man7.org/linux/man-pages/man1/ld.1.html :
--as-needed
--no-as-needed
This option affects ELF DT_NEEDED tags for dynamic libraries
mentioned on the command line after the --as-needed option.
Normally the linker will add a DT_NEEDED tag for each dynamic
library mentioned on the command line, regardless of whether
the library is actually needed or not. --as-needed causes a
DT_NEEDED tag to only be emitted for a library that at that
point in the link satisfies a non-weak undefined symbol
reference from a regular object file or, if the library is
not found in the DT_NEEDED lists of other needed libraries, a
non-weak undefined symbol reference from another needed
dynamic library. Object files or libraries appearing on the
command line after the library in question do not affect
whether the library is seen as needed. This is similar to
the rules for extraction of object files from archives.
--no-as-needed restores the default behaviour.
I'm trying to create a shared library on centos using gcc 4.8.2
shared library code:
//reload.c
int func(int num){
return num++;
}
link command:
gcc -fPIC -shared reload.c -o reload.so
use ldd command:
linux-vdso.so.1 => (0x00007ffe6aa93000)
libc.so.6 => /usr/lib64/libc.so.6 (0x00007f27feb97000)
/lib64/ld-linux-x86-64.so.2 (0x00007f27ff169000)
Now, Want to statically link glibc, how to write it?
like it:
ldd xxx.so
not a dynamic executable
I tried the build options, but the error.
gcc -fPIC -shared reload.c -o reload.so -Wl,-Bstatic -lc
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
thank you very much
You do not have dependencies to glibc at all for your code above, so the easiest way is to compile with the flag -nostdlib:
$ gcc -fPIC -shared reload.c -o reload.so -nostdlib
$ ldd reload.so
statically linked
From a function in a shared library, inside a running process (written in C), how do I discover where that shared library was loaded from?
All of the answers I've found involve using things such as ldd at the command line, or by peeking in /proc/self/maps.
On Win32, I'd just use GetModuleFileName(GetModuleHandle("foo.dll"), szPath, COUNTOF(szPath)). What's the Linux equivalent?
Bonus question: I need the same information in OS X.
You could use dl_iterate_phdr to iterate all loaded libraries and their segments (similar functionality is available for OSX, see e.g. this question). But most of the projects just parse /proc/self/maps.
As a side note, keep in mind that mappings may change dynamically (if libraries are loaded via dlopen) so reading them at startup may not be enough.
One method to achieve this is to make use of dladdr:
Code for the shared object:
$ cat so.c
#include <stdio.h>
#include <dlfcn.h>
void test_so_func()
{
Dl_info info;
if (dladdr(test_so_func, &info))
{
printf("Loaded from path = %s\n", info.dli_fname);
}
printf("hello\n");
}
Code for the main exec:
$ cat test.c
void test_so_func();
int main() {
test_so_func();
return 0;
}
Makefile:
$ cat Makefile
test: test.o libso.so
gcc test.o -o $# -Wl,-L.,-lso,-rpath,'$$ORIGIN'
clean:
-rm -f libso.so test.o test
libso.so: so.c
gcc -D_GNU_SOURCE=1 -fPIC -shared $< -o $# -lc -ldl
test.o: test.c
gcc -fPIC -c $< -o $#
Let's compile!
$ make
gcc -fPIC -c test.c -o test.o
gcc -D_GNU_SOURCE=1 -fPIC -shared so.c -o libso.so -lc -ldl
gcc test.o -o test -Wl,-L.,-lso,-rpath,'$ORIGIN'
Test this binary.
$ ./test
Loaded from path = /spare/scratch/1564054710/libso.so
hello
Verify that libso.so is indeed speaking the truth.
$ ldd ./test
linux-vdso.so.1 => (0x00007ffdf55d5000)
libso.so => /spare/scratch/1564054710/./libso.so (0x00007fbcc4602000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbcc4238000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fbcc4034000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbcc4804000)
The credit for this answer goes to https://github.com/mingwandroid
I have a C shared library named libtest.so which in turn use another shared library lihelp.so.
The code for libtest.so use dlopen() to load the libhelp.so
I have integrated libtest.so with my GO script gotest.go
When I run gotest.go after building and installing, I am seeing libtest.so is getting loaded successfully and function in libtest is executed successfully.
But the dlopen() call in libtest.so to load libhelp.so is failining with error "undefined symbol: dlopen"
But if I write a C application which use libtest.so all execution are fine withour any error.
Here is the code snippet of my Go file
/*
#cgo CFLAGS: -I./include
#cgo LDFLAGS: -L. -ltest -ldl
*/
Here is the Makefile entry for building libtest.so
CC = gcc # C compiler
CFLAGS = -c -fPIC -I./include # C flags
LDFLAGS = -shared -L/lib -ldl # linking flags
Can any one suggest what can be the problem?
Output of ldd of my go binary
ldd app
linux-gate.so.1 => (0xb77c3000)
libtest.so => ./libtest.so (0xb77bc000)
libgo.so.5 => /usr/lib/i386-linux-gnu/libgo.so.5 (0xb6ed0000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb6eb2000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb6d03000)
/lib/ld-linux.so.2 (0xb77c4000)
libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb6ce7000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb6ca1000)
I want to compile C code into one monolithic executable file (include every dependencies in this file) using GCC.
Usually I can compile the code with this command:
gcc -o server ex-serv-x509.c -lgnutls
But when I try to compile it with this -static argument I get this error:
[root#localhost test]# gcc -static -o server ex-serv-x509.c -lgnutls
/usr/bin/ld: cannot find -lc
collect2: ld returned 1 exit status
[root#localhost test]#
How I can solve the problem?
Best wishes
Try using the ldd command to see what it's linking in without the -static option. Here's what I get for a silly program I have.
~$ gcc so.o -lm -o so
~$ ldd so
linux-gate.so.1 => (0x00db7000)
libm.so.6 => /lib/libm.so.6 (0x00c7f000)
libc.so.6 => /lib/libc.so.6 (0x0037f000)
/lib/ld-linux.so.2 (0x002da000)
~$ gcc so.o -static -lm -o so
~$ ldd so
not a dynamic executable
So without the static I automagically get the shared version of libc, which surprised me even though it should not have. I imagine you have the shared version but not the static, so you'll need to get the static library from somewhere if you have decided that 1986 is the year for you :-).
To make sure you can do: gcc -print-search-dirs and search through them and make sure that libc.a is not to be found.