Static locals in methods and ELF OS ABI

Given the program

$ cat main.cpp #ifndef WITH_LOCAL_STATIC static int y = 0; #endif class X { public: void foo() { #ifdef WITH_LOCAL_STATIC static int y = 0; #endif ++y; } }; int main() { X().foo(); return 0; } 

compiled in two ways:

 $ g++ main.cpp -o global $ g++ main.cpp -DWITH_LOCAL_STATIC -o local 

I get two different binary formats:

 $ file local local: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x8d8e998601e44115b5fa6c0e71f3ed97cb13a0bd, not stripped $ file global global: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x3481ba7c6969ed9d1bd1c8ce0f052d574023d488, not stripped 

Can someone explain why I get ELFOSABI_LINUX in one case, but ELFOSABI_NONE in another? Compiler - gcc 4.7.2

The background is that in my environment, the loader rejects executable files that are not ELFOSABI_NONE .

+4
source share
1 answer

The GNU / Linux format has replaced the System V object file format, and your gcc believes that the minimum OS / ABI in which the executable can be run is GNU / Linux.

This usually happens when your program has characters of the type STT_GNU_IFUNC (GNU extensions that denote an indirect function), and these characters usually come from glibc. When you entered the local static variable gcc, the code added (more) to the translation block to handle its initialization and destruction (along the lines _ZZZ__static_initialization_and_destruction_iii ), and it was there that the corresponding parts of glibc were involved.

First of all, it is best to follow the advice in this question: How to avoid the STT_GNU_IFUNC characters in binary format?

Secondly, I have to say that on my box, both the old gcc 4.4 and the new clang 3.4 generate global and local binaries as standard ELF SYSVs , so either your test case is missing more of the corresponding bits and parts, or you maybe use custom and built-in gcc, custom linker or non-standard glibc.

Additional features you can take to find out how you ended up in these indirect GNU functions in your binary format:

  • Run nm in your binary and specify indirect characters, they must be of type i . (See below.)
  • Create a link map and / or assembly and draw these indirect symbols according to the specifics of your code.
  • Also, check if glibc detection was detected with ldd -v $(type -p gcc) for non-standard libc

i - for files in the PE format, this means that the symbol is in the section on the implementation of the DLL. For ELF files, this means that the symbol is an indirect function. This is a GNU extension for the standard ELF character type set. It indicates the symbol>, which, if the reference to the move is not evaluated at its address, but must be called at run time. Execution at run time will return the value that will be used when moving.

https://sourceware.org/binutils/docs/binutils/nm.html

0
source

Source: https://habr.com/ru/post/1489540/


All Articles