GetFileVersionInfo equivalent in Linux - c++

I'm porting a windows application to Linux, the application fetches version from a exe using Windows APIs GetFileVersionInfoSize() and GetFileVersionInfo(). But I'm unable to find something similar to that in Linux.
I'm aware that I can use readelf to read contents of application or object files in Linux as below
[root#Panch-Linux]# readelf <xyz.so> -h
ELF Header:
Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - Linux
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x4f7ec0
Start of program headers: 64 (bytes into file)
Start of section headers: 17823344 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 8
Size of section headers: 64 (bytes)
Number of section headers: 38
Section header string table index: 35
Shoud I use readelf to get the version information, if yes then the string "Version" is the one which actually represents the file version. Also please let me know how to use readelf in C++ programming on Linux environment.
If this is not the right way, please suggest me appropriate way of doing this.

Related

statically linked executable requires shared libraries

EDIT: i asked a wrong question, don't reed, see clarification below.
I have cross compiled two archive files a.a and b.a and statically linked them to an executable exe.elf .
I have verified (following these instructions)weather my executable is indeed statically using readelf -dhl exe.elf:
user#host:~/program/bin$ readelf -dhl exe.elf
ELF Header:
Magic: 7f 45 4c 46 01 01 01 03 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x12a45
Start of program headers: 52 (bytes into file)
Start of section headers: 13513704 (bytes into file)
Flags: 0x5000400, Version5 EABI, hard-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 40 (bytes)
Number of section headers: 40
Section header string table index: 39
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
EXIDX 0x11c558 0x0012c558 0x0012c558 0x047a0 0x047a0 R 0x4
LOAD 0x000000 0x00010000 0x00010000 0x120cfc 0x120cfc R E 0x10000
LOAD 0x120f48 0x00140f48 0x00140f48 0x05ab8 0x0aa9c RW 0x10000
NOTE 0x000114 0x00010114 0x00010114 0x00044 0x00044 R 0x4
TLS 0x120f48 0x00140f48 0x00140f48 0x00038 0x000a0 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
GNU_RELRO 0x120f48 0x00140f48 0x00140f48 0x040b8 0x040b8 R 0x1
Section to Segment mapping:
Segment Sections...
00 .ARM.exidx
01 .note.ABI-tag .note.gnu.build-id .rel.dyn .init .iplt .text __libc_freeres_fn __libc_thread_freeres_fn .fini .rodata __libc_subfreeres __libc_IO_vtables __libc_atexit __libc_thread_subfreeres .ARM.extab .ARM.exidx .eh_frame
02 .tdata .init_array .fini_array .data.rel.ro .got .data .bss __libc_freeres_ptrs
03 .note.ABI-tag .note.gnu.build-id
04 .tdata .tbss
05
06 .tdata .init_array .fini_array .data.rel.ro
There is no dynamic section in this file.
As this tells me, there is no dynamic section in this file.
nm | grep " U "
spits out nothing checking for dynamic dependencies:
ldd exe.elf
not a dynamic executable
also tells me this is a static executable.
When i transfer my program to my target computer (armv7) and try to execute it, it dares to tell me that i am missing shared objects.
user#target:/program/bin$ ./exe.elf
./exe.elf: error while loading shared libraries: libfirstlibrary.so: cannot
open shared object file: No such file or directory.
i dont have binutils on my target computer as this is a very minimal linux setup, which is part of the reason why i need to compile statically. My $LD_LIBRARY_PATH is empty, but i should not be needing it ... right?
I have compiled my apparently static executable exe.elf using the linaro toolchain with g++ -static -l:libfirstlib.a -l:libsecondlib.a as suggested in this post.
Can anybody help me clarify why my static library needs these shared objects? I will post further details if needed, i can't think of any more. Thanks.
EDIT:
Apparently i have accidentally copied the dynamically linked version of the program to the target without noticing it, ...twice... . Now that i transfered the actual static executable it works. I am very sorry.

Additional output from program built with the UB sanitizer of Clang

On travis CI where I use clang version 3.4 (tags/RELEASE_34/final) which is already installed, I build my code with this:
clang++ main.cpp -m64 -fsanitize=undefined -Werror -std=c++98 -pedantic -pedantic-errors -fvisibility=hidden -fstrict-aliasing -Weverything -Qunused-arguments -fcolor-diagnostics -O3 -DNDEBUG
(this command is obtained from compile_commands.json which is generated from cmake)
And in the output after the program quits some numbers (like hex representation of memory) appear:
00 00 00 10 70 fb 01 00 00 00 00 10 70 fb 01
My guess is this is from the UB sanitizer because when I build with ASAN or no sanitizer at all these numbers aren't there.
So what do they mean? How do I diagnose my UB error (if this is indeed such)?
I thought when a sanitizer encounters an error it crashes the program and prints a big message with explanation. So what is this?
This is a deal breaker for me because I compare reference output in a text file with the output of the program from the current build and such additional output breaks everything.
I tried locally using Clang 3.6, which is the default for my Ubuntu using the same build command, but when I run the executable I get no errors or such additional output.
here is the failing build on travis - and I don't think my code is relevant because my problem is with the sanitizer output not being helpful at all.
I also enabled the builds with clang 3.5/3.6/3.7/3.8 and turns out clang 3.5 behaves the same way...
clang 3.6 however gives more output!
20 6c 98 01 00 00 00 00 20 6c 98 01 00 00 00 00 20 6c 98 01
^
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/stl_tree.h:247:17: runtime error: upcast of address 0x00000115e090 with insufficient space for an object of type 'std::_Rb_tree_node<doctest::detail::TestData>'
0x00000115e090: note: pointer points here
00 00 00 00 00 00 00 00 00 00 00 00 20 6c 98 01 00 00 00 00 20 6c 98 01 00 00 00 00 20 6c 98 01
clang 3.7 and 3.8 give the same output as 3.6
I am using libstdc++ so I will switch to libc++ to hopefully remove this error (which I think is not from my code!)
I was using a simple TestData structure inside a std::set<>...

How can I know if an ARM library is using hardfp?

I don't have access to the build command, I just have the library in my system.
I guess I could build an hardfp executable that links against it and test, but I'm wondering if there's an easier way.
Execute readelf -A library.so: if the list of printed tags contains Tag_ABI_VFP_args: VFP registers, then it is a hardfp binary, otherwise assume softfp.
E.g. readelf -A /lib/arm-linux-gnueabihf/libm.so.6 will produce
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "7-A"
Tag_CPU_arch: v7
Tag_CPU_arch_profile: Application
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-2
Tag_FP_arch: VFPv3-D16
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int
Tag_ABI_HardFP_use: SP and DP
Tag_ABI_VFP_args: VFP registers
Tag_ABI_optimization_goals: Aggressive Speed
Tag_CPU_unaligned_access: v6
On the other side, readelf -A /lib/arm-linux-gnueabi/libm.so.6 produces
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "7-A"
Tag_CPU_arch: v7
Tag_CPU_arch_profile: Application
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-2
Tag_FP_arch: VFPv3-D16
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int
Tag_ABI_optimization_goals: Aggressive Speed
Tag_CPU_unaligned_access: v6
Use readelf.
Here's some example output from one an ARM build of Poco:
$ readelf libPocoFoundation.so -h
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: ARM
Version: 0x1
Entry point address: 0x61e50
Start of program headers: 52 (bytes into file)
Start of section headers: 1078048 (bytes into file)
Flags: 0x5000402, has entry point, Version5 EABI, hard-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 40 (bytes)
Number of section headers: 28
Section header string table index: 27
In the flags section, it will list data about the elf file. These are defined in the ARM ELF Specification, check table 4-2. In my case, this was built with a hard float compiler, so hard-float is listed as a flag.
On a soft float library, the flags line looks like this:
Flags: 0x5000202, has entry point, Version5 EABI, soft-float ABI
Use objdump -d to disassemble, then grep for some floating point commands. I'm not sure whether objdump will produce UAL-compliant assembly, so try old syntax too. It might be even easier to watch for register names rather than command mnemonics, but there could be false positives.

Linking to 32bit shared object file in 32 bit enviornment generates ELFCLASS64 error

System : I'm running 32 bit Ubuntu 12.04 on a i32 chipset.
Build Info : I'm using C++ 11 with Qt 4.8.1 and GCC.
Problem : I am developing a project that depends on in-house developed libraries hereafter mentioned to as slug. These libraries are built into .so files via the traditional "cmake ." then "make all" process. After the .so files are generated from cmake, I copy the .so files into a sub-directory of my project so that I can test that they are working before I install them into /usr/lib. Then I provide Qt (in my .pro file) with a absolute path to each library and build my application. My application finds these local libraries and compiles without errors or warnings. However, when I run my application (via command line) I receive the following error:
error while loading shared libraries: libslugSpec.so: wrong ELF class: ELFCLASS64
However, when I build the slug libraries on a 64 bit environment and link to them in a 64 bit environment my application runs perfectly. So, I figured I built the .so files for a 64 bit environment,and proceeded to edit the CMakeLists.txt file used to build the libraries. I add numerous 32 bit compilation and linking flags, shared object module flags, in addition to cuda (which slug relies on) bitness flags . No matter what combination of flags I tried, the libraries generated kept causing the error when running my application executable. So I decided to run the readelf -h command on each shared object file and check to see if they were really 64 bit. I found out that none of them are in fact, all producing logs similar to the following: (output for one of 3 .so files)
readelf -h libslugSpec.so
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x10150
Start of program headers: 52 (bytes into file)
Start of section headers: 511960 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 40 (bytes)
Number of section headers: 38
Section header string table index: 35
So now I am completely at a loss and can't seem to find an answer anywhere. Any illumination into how this could be happening would be a huge help.
For reference, here are the flags I am providing in the qt .pro file that builds my application:
QMAKE_CXXFLAGS += "-std=gnu++0x"
QT += core gui opengl
TARGET = source
TEMPLATE = app
CONFIG+= wwwidgets
#linux specific settings
unix:!macx{
LIBS += -lGLEW -lGLU /home/alex/Dropbox/brain-viz/source/lib/libslugUtil.so /home/alex/Dropbox/brain-viz/source/lib/libslugSpec.so /home/alex/Dropbox/brain-viz/source/lib/libslugSim.so
}
#windows specific settings
win32{
LIBS += -lglew32 -lwwwidgets4d
}
This error message:
error while loading shared libraries: libslugSpec.so: wrong ELF class: ELFCLASS64
Is not consistent with this output:
readelf -h libslugSpec.so
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Conclusion: you load a different version of libslugSpec.so from the one you ran readelf -h on.
Find out which libslugSpec.so is loaded at runtime by doing this:
LD_DEBUG=files,libs /path/to/your/executable
Then run readelf -h on that library, and confirm that it is in fact ELF64.
Finally replace it with the version you've built (or set LD_LIBRARY_PATH to pick up your version before "system" one), and the problem will be solved.

It is possible to read an object file?

I was curious about .obj files: I pretty much don't know what they are (or what they contain), so I opened them with Vim text editor and what I found inside was an Alien like language...
Is there any way to understand what they represent and what is their content
Also, for what are they being used ?
Thanks.
Sure.
But every different platform has a different object format. On Windows, you could use a tool like dumpbin (dumpbin comes with Visual Studio). On Linux, you could use "dumpobj", or disassemble the program.
Here's a good link for Linux:
http://www.linuxjournal.com/article/1060
PS:
objdump also lets you disassemble the object. Like you used to be able to do with "debug" on DOS PCs...
The .obj files used by link.exe has MS COFF format.
You can find "Microsoft PE and COFF Specification" here, and parse .obj file according to it.
Or, you can use existing tool like dumpbin.
The readelf tool is good at showing you some details on the data:
$ readelf -a /usr/bin/readelf
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
...
Some of its abilities to inspect specific sections of the executable can come in handy too:
$ readelf -p .rodata /usr/bin/readelf | more
String dump of section '.rodata':
[ 4] R_IA64_IMM14
[ 11] R_IA64_NONE
...
[ 1f58] Personality routine:
[ 1f70] __gcc_personality_v0
[ 1f85] __gxx_personality_v0
[ 1f9a] __gcj_personality_v0
[ 1faf] __gnu_objc_personality_v0
...
Actually disassembling the code is a bit of a stretch; if you compile your code with -g for debugging symbols, you can use readelf --debug-dump to read the program source, type information, etc.