Disabling __tls_get_addr_opt for PPC - c++

I develop software for an embedded device using the PowerPC architecture. Recently we got a new firmware upgrade and the manufacturer has provided a toolchain which is incapable of building runnable binaries.
Except for a few exceptions, where I've completely statically compiled the binary, the OS gives me following error:
isobuslog.bin: /lib/ld.so.1: version `GLIBC_2.22' not found (required by isobuslog.bin)
I've been up and down a multitude of mailing lists and threads all day, looking for a solution to this.
I finally read a post where following command was entered: powerpc-linux-gnu-readelf -Ws app/bin/isobuslog.bin | grep GLIBC_2.22
The output is as follows:
142: 00000000 0 FUNC GLOBAL DEFAULT UND __tls_get_addr_opt#GLIBC_2.22 (14)
Looking further in to the matter, it seems this is a thread-local storage optimisation routine which became available w/ GLIBC v2.22. Both the SDK I was provided and the SDK I installed myself both have GLIBC version higher than 2.22 and at least G++ 6.3 (6.3 provided by OEM, 9.2.1 installed locally on my machine) - so there's no way around this, unless I use the previous VM provided, which is based on an old Debian using GCC 4.6 - this is not an option, as we require C++11 and higher, without the use of Boost.
I've tried searching around some more, and have found these two linker flags which don't seem to work, causing the linker to exit with an error code, saying it couldn't recognise the flags provided.
--no-tls-optimize
--no-tls-get-addr-optimize
Is there a way to disable __tls_get_addr_opt so that my applications will build, or is there a way around this issue (except going back to ancient times)?

I've finally figured it out.
The trick is to tell G++ to pass the parameters to the linker.
This was achieved by adding the aforementioned switches to the comma-separated list like so:
-Wl,-rpath-link,${DEPS_DIR}/powerpc-linux-gnu/lib,--no-tls-optimize,--no-tls-get-addr-optimize

Related

Is profiling still possible after SPECTRE was fixed?

Since a couple of weeks I'm trying to profile a piece of numerical software and I'm unable to get useful results.
The code I'm profiling results in a huge function (__attribute__((flatten))) created out of many inlined functions and a few calls to std::exp/std::log/std::pow. This function is located inside a shared library and loaded via dlopen().
I've used
the google CPU profiler (hangs in the first fork() (interrupted by SIGPROF and restarted and interrupted and...) -- same problem with g++ option -pg)
linux tool perf (caused a reboot of the machine, I complained and they upgraded the OS (CENTOS 6.5). The results only highlight two assembler instructions out of above mentioned huge function. I don't have permissions to read accurate event sources (*:ppp))
some old version of vtune (difficult to operate, results are unreliable, no hardware drivers loaded)
sprof (results do not tell me anything as there is only a single function to profile -- when avoiding to use attribute flatten then the behavior is fully different)
I'm running
CENTOS 6.5
and
g++ (GCC) 5.3.0
I don't have any influence over the version of the OS or the compiler version.
I complained about the ancient OS some weeks ago, and they upgraded me to what I mentioned above.
In some former live I successfully used the google profiler -- when it was working (and not crashing or hanging due to signal handling problems) it provided useful results.
Anybody any comment?
Could all these unclear results be the result of the fixes for SPECTRE?
Do I need to insist, that certain profiling options are enabled on the machine?
Do I need to insist on the vtune drivers loaded?
Do I need to insist on an uptodate copy of vtune installed?
Compile with -fno-omit-frame-pointers?

Using GCC with new glibc and binutils to build software for system with older sysroot

I have a question since some months and I can't come to an answer with Google for a long time.
Background:
I am cross compiling software for arm based controllers which are running the linux distribution ptxdist. The complete linux image is built with a cross gcc (4.5.2) that was built against glibc-2.13 and binutils-2.21.
The c++ standard is quite old so I built a new toolchain which supports c++11 (gcc 4.8.5). It now is built against glibc-2.20 and binutils-2.24. I want to use that new compiler for my application software on the controller (not the complete image, just this one "main" binary) which is updated through a package management system.
The software seems to run. I just need to set LD_LIBRARY_PATH pointing to libstdc++.so.0.19 instead of libstdc++.so.14 for the binary. It does not accept the new libc, which is libc-2.20 instead of libc-2.13, though.
So binary uses libstdc++.so.0.19 and the rest of the system is unchanged.
Question:
Why is this working?
What risks could I expect running this software and should I anyway?
For example will the binary miss some functions of glibc-2.20 in future because it just gets glibc-2.13 on the target machine? Building gcc-4.8.5 against glibc-2.13 is not possible.
I have read so far that it depends on changes inside the ABI:
Impact on upgrade gcc or binutils
Here it is said that C Code is compatible if build by GCC4.1 to GCC 4.8.
Thank you!
glibc 2.14 introduced the memcpy#GLIBC_2.14 symbol, so pretty much all software compiled against glibc 2.20 will not work on glibc 2.13 because that symbol is missing there. Ideally, you would build your new GCC against glibc 2.13, not glibc 2.20. You claim that building GCC 4.8.5 against glibc 2.13 is not possible, but this is clearly not true in general.
Some newer C++ features will work with the old system libstdc++ because they depend exclusively on templates (from header files) and none of the new code in libstdc++.
You could also investigate how the hybrid linkage model works in Red Hat Developer Toolset. It links the newer parts of libstdc++ statically, while relying on the system libstdc++ for the common, older parts. This way, you get proper interoperability for things like exceptions and you do not have to install a newer libstdc++ on the target.
Good material for this could be here:
Multiple glibc libraries on a single host
Glibc vs GCC vs binutils compatibility
My final solution is this:
I built the GCC 4.8.5 as a cross compiler. I could not manage to build it with the older glibc2.13, only with version 2.20. It may be possible but in my case it did not work. Anyway, that is not a problem because I also built it with the sysroot-flag. Compiling new software depends completely on my old system, including C Runtime. I don't get a new C++ standard with this, but if you switch on compiler optimizations, I experienced better binary compression and performance.
Regarding a new C++ standard, I could link a newer libstdc++ which came with my cross compiler using -l:libstdc++.so.6.0.19 as LDDFLAG. Therefore I only need to copy an additional libstdc++ on my target beside the old libstdc++.
After having a look into the symbols used by the new lib using
strings libstdc++.so.6.0.19 | grep GLIBC_
you can observe that it doesn't depend on any newer symbols than GLIBC_2.4. It looks like I could never run into the problem of missing symbols.
So in my case I have luck using a new C++11 standard without having any changes in the rest of the system. If there are introduced new symbols you need to follow the above links in my post which are pretty informative. But I would never try that for myself. In my case, with the GCC 4.9.4, libstdc++.so.6.0.20 got symbols pointing to GLIBC_2.17. That could give me trouble as I am cross compiling with GLIBC_2.13.

Am I able to use C++11 in QNX?

I have some cross-platform code with some C++11 features like #include <thread> and others. I will soon be using a QNX 6.6 board, and I'm wondering if my code can compile on it, and which features will be available.
QCC is the official QNX C++ compiler, but I can't find any documentation citing which C++11 features, or even which C++ features in general, it supports. Is this a wrapper around GCC or its own thing? Either way, can I get or compile other compilers on this platform?
From what I know qcc is just using gcc internally. Because of this you can use all functionalities provided by the version of gcc that QNX decided to put into their package.
Judging from the release notes of QNX 6.6 gcc 4.7 is used:
GCC 4.7 tool chain, including support for the Intel Advanced Vector Extensions (AVX)
GDB 7.5
New: Binutils 2.24
Python 2.7.5, as a host-side tool
The release notes provide a link to information about gcc 4.7 but I think this link better shows which specific features are supported. There is too much information on the linked page, because of that I do not copy it. But in essence the link states:
GCC provides experimental support for the 2011 ISO C++ standard. This support can be enabled with the -std=c++11 or -std=gnu++11 compiler option ... GCC's C++11 mode implements much of the C++11 standard produced by the
ISO C++ committee
Whereas #Marged's answer seems to cover absolutely every important aspect of your question, I'd like to add that it is also possible to get more current versions of all GNU dev tools (like gcc, gdb or make..). This is officially provided by the QNX staff for "experimental use only", I guess1. But so far I've had only good experiences with them.
Check out QNX's updated Core Development Tools
(You need to register to the QNX community portal first to open the link)
You would then update your Linux dev system like that:
Get files from here
Binutils
GCC
Extract files into a new folder
(do not extract and overwrite existing folder directly since it might be that symbolic links don't get updated)
that should create the host and the target folder
Copy & paste the new files into the actual QNX folder and overwrite existing files
Optionally: update the config default file's value to the new compiler version
e.g. /../qnx650/host/linux/x86/etc/qcc/gcc/default
make sure 32bit libraries are installed (if not):
$ sudo apt-get install lib32stdc++6
if not installed correctly errors like the following can occur
$ i486-pc-nto-qnx6.5.0-g++: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
1 Official text:"Stable versions of the Core Development Tools are included as part of QNX Momentics. You can download updated versions of these tools currently being developed through this project and benefit from their enhancements earlier!"
The version of gcc that is used by qcc does support much of the C++11 specification. I've used it. Just add -std=c++11 to the compiler line.
I did find one issue with C++11 support on QNX 6.6. This was in July 2014, so things may have changed. The support of vector initialization (std::vector<int> {1,2, 3, 4};) in the C++11 library shipped with QNX 6.6 was broken. Code would compile cleanly, but then fail rather cryptically when run. Again, I don't currently know the current status of this issue, so YMMV.

Undefined reference to mempcy#GLIBC_2.14 when compiling on Linux

I am trying to port an application to drive a device that uses an ftdi2332h chip from windows to linux. I installed the libftd2xx library on an ubuntu 10.04 system per these instructions.
When I try to compile any of the sample programs I get the following error:
/usr/local/lib/libftd2xx.so: undefined reference to `memcpy#GLIBC_2.14'
collect2: ld returned 1 exit status
Any guidelines on how to fix this?
The mempcy#GLIBC_2.14 is called a versioned symbol. Glibc uses them while other runtime libraries like musl do not.
The significance of mempcy#GLIBC_2.14 when compiling on Linux is due to Glibc changing the way memcpy worked back in 2012. memcpy used to copy bytes {begin → end} (low memory address to high memory address). Glibc 2.13 provided an optimized memcpy that copied {end → begin} on some platforms. I believe "some platforms" included Intel machines with SSE4.1. Then, Glibc 2.14 provided a memcpy that restored the {begin → end} behavior.
Some programs depended upon the {begin → end} copy. When programs used overlapping buffers then memcpy produced undefined behavior. In this case a program should have used memmove, but they were getting by due to a copy that occurred {begin → end}. Also see Strange sound on mp3 flash website (due to Adobe Flash), Glibc change exposing bugs (on LWN), The memcpy vs memmove saga and friends.
To fix it it looks like you can add the following to your source code:
__asm__(".symver memcpy,memcpy#GLIBC_2.2.5");
Maybe something like the following. Then include the extra source file in your project.
$ cat version.c
__asm__(".symver memcpy,memcpy#GLIBC_2.2.5");
The readme mentions Ubuntu 12.04, which comes with glibc 2.15. You are using Ubuntu 10.04, which comes with glibc 2.11.1. The error message you are seeing is telling you some binary (here it is most likely libftd2xx.so) you linked to relies on a newer glibc than you are linking, which is logical, given the previous fact.
Either recompile libftd2xx.so from source against your system's glibc version (probably not an option, as it's binary only), or update your OS. Ubuntu 10.04 is quite old.
As a last resort (and only try to do this if you like, euhm, hitting your fingers with a sledgehammer), you can compile a newer glibc for your system, and install it somewhere like /opt.
This is an Oracle Bug with "opatchauto". See this Url, https://dba010.com/2019/06/24/19cgi-12crdbms-opatchauto-re-link-fails-on-target-procob/.
WORK-AROUND: Manually use “opatch”, instead of “opatchauto” for each of the applicable DB Patches.
You can download and compile libc, and install under /opt/lib/libcX/libc.so.6. Then, you can have a script:
LD_LIBRARY_PATH=/opt/lib/libcX:/lib/:/usr/lib:/usr/share/lib
./your_program
I'm not sure, but if it is a cross-compiler you're using, you must have compatible versions of the basic libraries installed somewhere (not in /usr/include and /usr/lib), and you must ensure that the compiler uses them, and not the ones for the native compiler. And you must ensure that the entire tool chain is version compatible. (And I know that this isn't a very complete answer, but it's all I know.)
Upgrade to Ubuntu 12.04. I had the same thing happen using Qt, it turned out the glibc library was too old. Googling around indicated that trying to upgrade glibc on one's own is a very dangerous proposition.

Anticipate "kernel too old" errors between 2.6.16 and 2.6.26 kernel versions

I build an application on a machine running Linux (Debian) with kernel 2.6.26-2-amd64 and I want to run this application on another machine running Linux (Suse) with kernel 2.6.16.60-0.21-smp but I get the error "FATAL: kernel too old".
I know from research on the internet that this can happen when building against a glibc library that was not compiled to support older kernel versions, but it usually concerns version 2.4. Is it possible to get such errors for kernel of the same series (2.6) or can this be from something else ?
Additionally I read that the solution to this problem is to rebuild the application against another version of glibc compiled with appropriate --enable-kernel=VERSION option. As an alternative can you just dynamically link your application with glibc to solve the problem ?
Thank you for your help.
UPDATE: I understand my question may seem vague or solved by one of the solutions already mentionned (dynamically linking, building on another [virtual] system, rebuilding glibc [which seems quite tricky considering the comments I read about it]) but what I am ultimately looking for are ways to prevent such problems.
For instance, is it possible to find which versions of the Linux kernel are compatible with a particular build of glibc ?
UPDATE 2: I eventually found a source patch for glibc (for Debian but I guess there are similar docs online for other distros) that (I guess) contains the information I was looking for.
From this page:
--- eglibc-2.11.2.orig/debian/sysdeps/linux.mk
+++ eglibc-2.11.2/debian/sysdeps/linux.mk
## -0,0 +1,51 ##
[...]
+MIN_KERNEL_SUPPORTED := 2.6.18
[...]
+# Minimum Kernel supported
+with_headers = --with-headers=$(shell pwd)/debian/include
--enable-kernel=$(call xx,MIN_KERNEL_SUPPORTED)
[...]
Which explains the "kernel too old" error. Hope it helps other people.
One way you can determine the minimum kernel version for a given ELF file is to run file on it, like so:
$ echo 'int main(){}' > test.c
$ gcc -o test test.c
$ file test
test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.38, not stripped
The important part here is the "for GNU/Linux 2.6.38", which indicates the minimum kernel version.