Bug 1570853
Summary: | linker wrapper scripts corner cases should be documented | ||
---|---|---|---|
Product: | Red Hat Developer Toolset | Reporter: | Mark Wielaard <mjw> |
Component: | doc-User_Guide | Assignee: | Vladimír Slávik <vslavik> |
Status: | CLOSED CURRENTRELEASE | QA Contact: | |
Severity: | unspecified | Docs Contact: | |
Priority: | unspecified | ||
Version: | DTS 7.0 RHEL 7 | CC: | jakub, jhradile, kanderso, lkuprova, mcermak, mjw, mnewsome, mpolacek, ohudlick, vslavik |
Target Milestone: | alpha | ||
Target Release: | 7.1 | ||
Hardware: | Unspecified | ||
OS: | Unspecified | ||
Whiteboard: | |||
Fixed In Version: | Doc Type: | Known Issue | |
Doc Text: |
Specify libraries after object files when linking with GCC
In Red Hat Developer Toolset, libraries are linked via linker scripts which might specify some symbols through static archives. This is required to ensure compatibility with multiple versions of Red Hat Enterprise Linux. However, the linker scripts use names of the respective shared object files. As a consequence, the linker uses different symbol handling rules than expected, and does not recognize symbols required by object files when the option adding the library is specified before options specifying the object files, such as:
gcc -lsomelib objfile.o
Such use of a library from Red Hat Developer Toolset results in linker error messages "undefined reference to symbol". To enable successful symbol resolution and linking, follow the standard linking practice and specify the option adding the library after the options specifying the object files:
gcc objfile.o -lsomelib
Note that this recommendation applies when using the version of GCC available as a part of Red Hat Enterprise Linux, too.
|
Story Points: | --- |
Clone Of: | Environment: | ||
Last Closed: | 2018-08-01 10:49:11 UTC | Type: | Bug |
Regression: | --- | Mount Type: | --- |
Documentation: | --- | CRM: | |
Verified Versions: | Category: | --- | |
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
Cloudforms Team: | --- | Target Upstream Version: | |
Embargoed: |
Description
Mark Wielaard
2018-04-23 14:24:58 UTC
Better workaround, put the -lelf last: $ gcc -o test_elf test_elf.c -lelf $ ./test_elf $ echo $? 0 Consensus seems to be that this isn't really a bug, just a slight difference caused by the implementation of the library wrapper scripts that needs documenting because things work slightly differently between the base RHEL toolchain and the DTS toolchain that uses linker script wrappers for libraries. The issue seen comes from DTS using wrapper scripts for various libraries to define some or all symbols through static archives and the follow ld linker "rule" (see the ld(1) manual page): 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. The base RHEL toolchain doesn't normally use static archives but only shared library objects. When using the shared library object a symbol definition will be resolved at runtime by loading the shared library. But DTS defines some (or all) symbols in core libraries through a linker script wrapper that pulls in symbols through archive. This is done to make sure an executable produced by the DTS toolchain can be used as is on base RHEL without the user needing to install DTS shared libraries just to run the executable. This does mean that the user has to be careful that objects defining symbols are put on the linker (or compiler) command line after those objects that use those symbols. Most build systems (like automake) already make sure libraries used by a program are listed last on the command line. An example is the following program that uses the elf_version symbol from the libelf.so library. #include <elf.h> #include <libelf.h> int main (int argc, char **argv) { return (elf_version (EV_CURRENT) == EV_CURRENT) ? 0 : 1; } With the base RHEL toolchain this could be build as follows: $ gcc -lelf -o test_elf test_elf.c This produces a executable that dynamically links against libelf.so and resolves the elf_version symbol at runtime. But with the DTS toolchain the libelf.so file is actually a linker wrapper script that pulls in some symbol definitions through an static archive. So having the -lelf argument too early on the command line will result in: $ scl enable devtoolset-7 bash $ gcc -lelf -o test_elf test_elf.c /tmp/ccFlPTwb.o: In function `main': test_elf.c:(.text+0x15): undefined reference to `elf_version' collect2: error: ld returned 1 exit status The correct way to build this program is to have the -lelf argument at the end. $ gcc -o test_elf test_elf.c -lelf This will work with both the base RHEL toolchain and the DTS toolchain. |