I have multiple Fortran static libraries which have functions with the same name, that I'd like to call from Rust. Using objcopy prefixing, I can make the names unique, as shown here:
ld -r obj1.o obj2.o ... objn.o -o static1.o
objcopy --localize-hidden --prefix-symbols=foo static1.o static2.o
ar -rcs mylib.a static2.o
However, it seems that objcopy prefixes all symbols, even the ones that only appear as a function call to an external library. Thus, I get errors such as:
/usr/bin/ld: (.text+0xaf0c): undefined reference to `foo_gfortran_runtime_error_at'
It seem then that I only want to rename the symbols that are marked as T in nm. Is this correct? Is there a way to do this with objcopy or ld?
Do you also know of a solution that works on Mac as well (where objcopy is unavailable)?
Related
I am trying to understand static libraries and shared objects in C. I am trying to understand whether one type of library can depend on other type.
Consider a scenario:
libA.so has a function foo_A_dyn():
libA.so ---> foo_A_dyn()
foo_A_dyn() uses a function foo_B_static() which is defined in libB.a which is a static library.
libB.a ---> foo_B_static()
I have built my libraries in the following way:
gcc -c foo_B.c -o foo_B.o
ar -cvq libB.a foo_B.o
gcc -fPIC -c foo_A.c -o foo_A.o
gcc -shared libA.so foo_A.o -I.
gcc main.c -lA -lB -L. -I. -o EXE
Note: main.c makes call to foo_A_dyn() and does NOT call foo_B_static() directly.
And now when I am trying to build my executable EXE, I am getting the error "undefined reference to foo_B_static".
I think the error seems genuine but I am not able to decode the rationale behind this and put it to words.
Can someone please help?
From gcc link options:
-llibrary
-l library
...
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.
Try:
gcc main.c -lB -lA -L. -I. -o EXE
Here's what the linker is doing. When we link our executable ('EXE' above) it has some symbols (functions and other things) that are unresolved. It will look down the list of libraries that follow in sequential order, trying to resolve unresolved symbols. Along the way, it finds that some of the symbols are provided by libB.so, so it notes that they are now resolved by this library. While going through libB.so it finds some symbols which are unresolved and it tries to resolve them by looking up the library that follows.
When we are ordering the libraries like:
gcc main.c -lA -lB -L. -I. -o EXE
Linker is not able to lookup for the definition of symbols used in libB into libA. Reason could be that backward reference is not available.
I have also figured out that:
shared object can depend on a static archive,
a static archive can depend on a shared object, and
one static archive can depend on another static archive
Please let me know if I have erred somewhere.
I have an libfoo.a which contains _start and all required symbols for an executable. ld.bfd -o foo libfoo.a works smoothly in my case. However, ld.gold -o foo libfoo.a fails silently generating an executable with no symbols from libfoo.a. Creating an empty a.o and link it with ld.gold -o foo a.o libfoo.a works.
I was wondering is there any way to directly link a static library into an executable using ld.gold without creating a redundant empty object files?
You can specify the entry symbol explicitly with the -e _start option, and the linker will use that to decide that it needs to load the object that defines it.
Unfortunately, gold will not use the implicit start symbol to load an object from the archive library.
When compiling our project, we create several archives (static libraries), say liby.a and libz.a that each contains an object file defining a function y_function() and z_function(). Then, these archives are joined in a shared object, say libyz.so, that is one of our main distributable target.
g++ -fPIC -c -o y.o y.cpp
ar cr liby.a y.o
g++ -fPIC -c -o z.o z.cpp
ar cr libz.a z.o
g++ -shared -L. -ly -lz -o libyz.so
When using this shared object into the example program, say x.c, the link fails because of an undefined references to functions y_function() and z_function().
g++ x.o -L. -lyz -o xyz
It works however when I link the final executable directly with the archives (static libraries).
g++ x.o -L. -ly -lz -o xyz
My guess is that the object files contained in the archives are not linked into the shared library because they are not used in it. How to force inclusion?
Edit:
Inclusion can be forced using --whole-archive ld option. But if results in compilation errors:
g++ -shared '-Wl,--whole-archive' -L. -ly -lz -o libyz.so
/usr/lib/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x1d): undefined reference to `__init_array_end'
/usr/bin/ld: /usr/lib/libc_nonshared.a(elf-init.oS): relocation R_X86_64_PC32 against undefined hidden symbol `__init_array_end' can not be used when making a shared object
/usr/bin/ld: final link failed: Bad value
Any idea where this comes from?
You could try (ld(2)):
--whole-archive
For each archive mentioned on the command line after the --whole-archive option, include every object file in the
archive in the link, rather than searching the archive for the required object files. This is normally used to turn
an archive file into a shared library, forcing every object to be included in the resulting shared library. This
option may be used more than once.
(gcc -Wl,--whole-archive)
Plus, you should put -Wl,--no-whole-archive at the end of the library list. (as said by Dmitry Yudakov in the comment below)
I have two static library files (.a) and one bitecode file (.bc) ,which created with an opt pass.In this bitecode file i have added my own code and in this code i need to call a function which is declared in the static libraries. I 've noticed that the llvm-ld tool no longer exists for clang newer versions so i tried two different ways to link these three files (two libraries and one bitecode file):
1. try to link with gcc :
create with llc the object file of file.bc
$llc -filetype=obj file.bc -o file.o
link object and libs with gcc
$gcc -I lib1.a lib2.a -O3 file.o -o file
these commands give me this error:
file.o: In function `main':
file.bc:(.text+0xc0): undefined reference to `function_in_lib'
collect2: error: ld returned 1 exit status
(function_in_lib is the function that i need to call from lib and compilers can't find this function)
2. the second way is with ld command
create with llc the object file of file.bc
$llc -filetype=obj file.bc -o file.o
link object and libs with ld
$ld -o linked lib1.a lib2.a file.o -lc
these commands give me this error:
ld: warning: cannot find entry symbol _start; defaulting to 00000000004002b0
new.o: In function `main':
new.bc:(.text+0xc0): undefined reference to `function_in_lib'
i tried to change the order of arguments but i have more errors when i did it.I think that the fault become from the linking,any idea?
The reason you're getting undefined references is because you're linking your libraries in the wrong way. A linker works in an incremental order - it looks at the first file you provided and gathers a list of things that file references but can't be found. Then the linker moves onto the next library and does the same thing, but also looks for opportunities to fix the undefined references from the previous libraries.
The reason that ld can't find function_in_lib is because it links file.o after the libraries and therefore doesn't get a chance to fill in the references that file.o requires. If you're looking for more specifics about linking and why you're running into this problem, this is a pretty good introduction.
If you just want to fix your problem, move the library files to after file.o in your command, i.e.
ld -o linked file.o lib1.a lib2.a -lc
I've got two shared libraries libA and libB, and I want to create a new library libC, that links to both libraries, so I can link my application with -lC instead of -lA and -lB.
I can't use -lA and -lB one, because I'd have to fix many packages otherwise.
libB is a precompiled binary.
I tried to run this:
gcc -fPIC -shared -o libA.so A.c
gcc -shared -Wl,--no-as-needed -L. -lA -lB -o libC.so
But when I link my application, that needs libB with -lC I
App.o: undefined reference to symbol 'SymbolInB'
note: 'SymbolInB' is defined in DSO libB.so so try adding it to the linker command line
libB.so: could not read symbols: Invalid operation
If I run readelf -a libB.so I see the SymbolInB in .dynsym, it is missing in libC.so. So I assume I miss a linking option to resolve the symbols correctly?
It doesn't work that way. The functions in libC can use the functions in libA and libB fine, because libC was linked with the other libraries. However, those symbols from libA and libB are not exported from libC, so if you have an application which directly uses functions from libB then you need to link with libB.