gcc shared library failed linking to glibc - c

I'm writing a simple C shared library using Eclipse CDT under Linux 64bit.
The code has one reference to the rand() function in the <stdlib.h> It compiles fine but when linking it reports the following error from the linker:
gcc -shared -o "libalg.so" ./sort.o
/usr/bin/ld: ./sort.o: relocation R_X86_64_PC32 against undefined symbol `rand##GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
sort.o is the object file compiled from the file. libalg.so is the target shared library name.
Can anyone explaining why this happen?
Thanks.

On x86_64 architecture gcc requires you to use -fPIC i.e Position Independent Code by default.
The underlying reason for the error is that the relocation type for the symbol rand is of type R_X86_64_PC32 which means that it is PC relative and should lie within 32bit offset from the following instruction.
But the current architecture is of x86_64 type which means that it can lie anywhere within the 64bit address space.
So the dynamic linker actually can not link a symbol with such a relocation type.
Either you have to use -fPIC or compile your code using the -mcmodel=large which will actually make the relocation type to R_X86_64_64.
For more details on how linking is done refer to this great blog by Eli Bendersky

Related

why cannot use R_X86_64_PC32 with shared libs

It seems to not be possible to build a shared lib from relocable objects with R_X86_64_PC32 references and I don't understand why.
These references are IP relative and so are position independent. So why ld tell me this is not the case and I have to use -fPIC which generate a GOT reference ?
relocation R_X86_64_PC32 against symbol `infolib' can not be used when making a shared object; recompile with -fPIC
As it is said here : Difference in position-independent code: x86 vs x86-64
IP-relative offset does not work for shared libraries, because global symbols can be overridden, so x86-64 breaks down when not built with PIC.
We have to use -fPIC to go through GOT which is updated at runtime for symbol overriding.

C access symbol in executable (linux)

I have an executable binary with many symbols. I am trying to figure out how to access those symbols in my code. dbg can so I know its possible im just not sure how. I cannot create a shared object from it with "gcc -shared -o myexe.so myexe" because there are multiple definitions of the same function
...(.data+0x8e8): first defined here
/usr/bin/ld: warning: Cannot create .eh_frame_hdr section, --eh-frame-hdr ignored.
/usr/bin/ld: error in fipstest(.eh_frame); no .eh_frame_hdr table will be created.
/usr/bin/ld: fipsttest.so: No symbol version section for versioned symbol `NSSUTIL_ArgGetLabel##NSSUTIL_3.14'
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
This means that gcc cannot link to it during compile time with -L because the of the same issue.
the nm command shows all the symbols and the one I want. If I could modify the symbol table to remove all the exports but the ONE I need then it might work but I can't find how to do that. Or if anyone could point me in the right direction to access a binary during runtime and load a function with a physical address that would work too. Any help is appreciated. Thank you.

How to access -ldl in cross compiler in SDK

i am using Xilinx SDK with cross compiler as aarch64-none-elf-gcc
i am loading a shared library in my program and i am getting error as
Building target: fsbl.elf
Invoking: ARM v8 gcc linker
aarch64-none-elf-gcc -L"/proj/ssw_xhd/boot/balakrish/workspace/hello_world/Debug" -Lwrk/released/2017.3/GA/2017.3_1005_1/installs/lin64/SDK/2017.3/gnu/aarch64/lin/aarch64-none/bin/../lib/gcc/aarch64-none-elf/6.2.1/../../../../aarch64-none-elf/bin/ld -Wl,-T -Wl,../src/lscript.ld -L../../fsbl_bsp/psu_cortexa53_0/lib -o "fsbl.elf" ./src/psu_init.o ./src/xfsbl_authentication.o ./src/xfsbl_board.o ./src/xfsbl_bs.o ./src/xfsbl_csu_dma.o ./src/xfsbl_dfu_util.o ./src/xfsbl_exit.o ./src/xfsbl_handoff.o ./src/xfsbl_hooks.o ./src/xfsbl_image_header.o ./src/xfsbl_initialization.o ./src/xfsbl_main.o ./src/xfsbl_misc.o ./src/xfsbl_misc_drivers.o ./src/xfsbl_nand.o ./src/xfsbl_partition_load.o ./src/xfsbl_plpartition_valid.o ./src/xfsbl_qspi.o ./src/xfsbl_rsa_sha.o ./src/xfsbl_sd.o ./src/xfsbl_translation_table.o ./src/xfsbl_usb.o -lhello -Wl,--start-group,-lxil,-lgcc,-lc,--end-group -Wl,--start-group,-lxilffs,-lxil,-lgcc,-lc,--end-group -Wl,--start-group,-lxilsecure,-lxil,-lgcc,-lc,--end-group -Wl,--start-group,-lxilpm,-lxil,-lgcc,-lc,--end-group -n
/tmp/ccjtx6CQ.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x18c): undefined reference to `dlopen'
<artificial>:(.text.startup+0x18c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `dlopen'
<artificial>:(.text.startup+0x19c): undefined reference to `dlsym'
<artificial>:(.text.startup+0x19c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `dlsym'
<artificial>:(.text.startup+0x1a4): undefined reference to `library_function'
<artificial>:(.text.startup+0x1a4): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `library_function'
<artificial>:(.text.startup+0x1ac): undefined reference to `dlclose'
<artificial>:(.text.startup+0x1ac): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `dlclose'
collect2: error: ld returned 1 exit status
make: *** [fsbl.elf] Error 1
Finally my question is how to load -ldl in cross compiling
if i use -ldl in C/C++ Build settings-.libraries->library paths . I am getting error as
/wrk/released/2017.3/GA/2017.3_1005_1/installs/lin64/SDK/2017.3/gnu/aarch64/lin/aarch64-none/bin/../lib/gcc/aarch64-none-elf/6.2.1/../../../../aarch64-none-elf/bin/ld: cannot find -ldl
collect2: error: ld returned 1 exit status
make: *** [fsbl.elf] Error 1
Different parts of your answer seem to conflict.
dlopen, dlsym and friends are used to load code from another file on the filesystem. In other words, these functions are related to loading code, at runtime, from a library available on the target platform filesystem and operating system.
In the case of cross compiling, the toolchain needs to provide the library (libdl.so or libdl.a) that has the implementaiton of those functions. The toolchain provide the code that has the relevant operating system calls to open the file with the code, map it to memory and link it into the running program.
Which is where the conflict comes into play. The toolchain you mention seems to be bare metal toolchain. In other words, this is a tool chain for running your code directly on the chip, with no operating system. If you have no operating system, it should be obvious that you cannot use it in order to load further code at runtime.
With that in mind, it should be obvious why the tool chain does not supply you with a suitable implementation of libdl.a. It cannot be generically implemented on the platform.

Creating a dylib which gets linked at runtime

I am trying to create a dynamic library which is meant to be linked and loaded into a host environment at runtime (e.g. similar to how class loading works in Java). As such, I want the dynamic library to be left with a few "dangling" references, which I expect it to pick up from its host environment when it is loaded into that environment.
My problem is that I cannot figure out how to create the dynamic library without explicitly linking it to existing symbols. I am hoping to produce a dynamic library that does not depend on a specific host executable (or host library), rather one that is able to be loaded (e.g. by dlopen) in any host as long as the host makes a couple symbols available for use.
Right now, any linking command I've tried results in a complaint of missing symbols. I'd like it to allow symbols to be missing (ideally, just particularly specified symbols).
For example, here's a transcript with the error on OS X:
$ cat frotz.c
void blort(void);
void run(void) {
blort();
}
$ cc -c -o frotz.o frotz.c
$ cc -dynamiclib -o libfrotz.dylib frotz.o
Undefined symbols for architecture x86_64:
"_blort", referenced from:
_run in frotz.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
If I do the same thing using a GNU toolchain (on Linux), it helpfully tells me:
$ gcc -shared -o libfrotz.so frotz.o
/usr/bin/ld: frotz.o: relocation R_X86_64_PC32 against undefined symbol `blort'
can not be used when making a shared object; recompile with -fPIC
and indeed, adding -fPIC to the C compile command seems to fix the problem in that environment. However, it doesn't seem to have any effect in OS X.
All the other dynamic-linking questions I could find on SO seem to be about the more usual arrangement of libraries, where a library is being built to be linked into an executable before that executable runs, rather than the other way around. The closest related question I found was this:
Can an executable be linked to a dynamic library after its built?
which unfortunately has very little info, none of it relevant to the question I'm asking here.
UPDATE: I distilled the info from the answer along with everything else I'd figured
out, and put together this example:
https://github.com/danfuzz/dl-example
As far as my knowledge goes, you want to use weak linkage:
// mark function as weakly-linked
extern void foo() __attribute__((weak));
// inform the linker about that too
clang -dynamiclib -o bar.dylib bar.o -flat_namespace -undefined dynamic_lookup
If a weak function can be resolved at runtime, it will then be resolved. If it can't, it will be NULL, instead of generating a runtime (or, obviously, link-time) error.

shared library relocation R_X86_64_PC32 error

I am trying to make 32 bit library on a 64 bit Ubuntu box. I am creating .so as follows
gcc - shared -Wl,-soname,libtest.so *.o
I am getting /usr/bin/ld : relocation R_X86_64_PC32 against symbol "set_bright' cann't be used when making shared object;recompile with -fPIC.
Already I tried compiling with -fPIC. It didn't work.
Please let me know if I need to use any flag while compilation .c or some flag while creating .so
thanks,
I believe you get that error if there you're calling a function declared as hidden, e.g.
int set_hidden(void) __attribute__((visibility("hidden")));
and it's not defined in the same shared object.
To solve it you have to also link the object file containing the definition of set_hidden, or remove the call to it.

Resources