"wrong ELF class: ELFCLASS32", but only when using GDB - linux

I'm trying to run dfhack in a debugger. I'm running 64-bit Ubuntu Trusty, but Dwarf Fortress does not have a 64-bit build so I'm running 32-bit Dwarf Fortress. I have installed gdb via apt-get install gdb:i386.
Here's what happens when I start dfhack with gdb:
ben#australium:~/df_linux$ xvfb-run -a ./dfhack --gdb
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./libs/Dwarf_Fortress...(no debugging symbols found)...done.
(gdb) start
Temporary breakpoint 1 at 0x804bdec
Starting program: /home/ben/df_linux/libs/Dwarf_Fortress
ERROR: ld.so: object './hack/libdfhack.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
Temporary breakpoint 1, 0xf7598b53 in main ()
from /home/ben/df_linux/libs/libgraphics.so
(gdb)
Here's what happens when I run it without gdb:
ben#australium:~/df_linux$ xvfb-run -a ./dfhack
Xlib: extension "RANDR" missing on display ":99".
Loading bindings from data/init/interface.txt
New window size: 1280x720
Font size: 10x12
Resizing grid to 128x60
Resizing font to 10x12
Resetting textures
DFHack is ready. Have a nice day!
Type in '?' or 'help' for general help, 'ls' to see all commands.
[DFHack]#
The executable, the preloaded library, and gdb are all 32-bit:
ben#australium:~/df_linux$ readelf -h /home/ben/df_linux/libs/Dwarf_Fortress
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: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x804c980
Start of program headers: 52 (bytes into file)
Start of section headers: 18192664 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 8
Size of section headers: 40 (bytes)
Number of section headers: 28
Section header string table index: 27
ben#australium:~/df_linux$ readelf -h /home/ben/df_linux/hack/libdfhack.so
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: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x1b7e40
Start of program headers: 52 (bytes into file)
Start of section headers: 43686636 (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: 37
Section header string table index: 34
ben#australium:~/df_linux$ readelf -h /usr/bin/gdb
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: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x808cb95
Start of program headers: 52 (bytes into file)
Start of section headers: 5089368 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 9
Size of section headers: 40 (bytes)
Number of section headers: 28
Section header string table index: 27

ERROR: ld.so: object './hack/libdfhack.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
This error comes from GDB starting your (64-bit) shell, which in turn execs your (32-bit) dfhack program.
You should only care about preloading into the target program. The fact that libdfhack.so was not preloaded into your shell is of no consequence, and you should simply ignore it.

Related

Why does not entry point address start at 0x400000

On Ubuntu 20.10 x86_64
my sample code:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("helloworld\n");
return 0;
}
Build:
gcc -o test test.c
Show entry point address:
readelf -h ./test
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: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1060
Start of program headers: 64 (bytes into file)
Start of section headers: 14824 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 30
Why does entry point address start at 0x1060 ? not 0x40000 ?
The binary is relocatable, and the segments have been packed against each other. The .text segment starts at 0x1050 in the file, and the entry point is relative to its location in the file, not the location it will ultimately be loaded.
For a non-relocatable file try readelf -h /usr/lib/klibc/bin/sh. This file is simpler in a number of ways, including not using an interpreter but actually being loaded as-is by the kernel.
We're not in x86 anymore. Relocatable binaries are the default for everything now, not just shared libraries. It's no longer a great pain to do relocatable stuff, and in a certain way it's cheaper than non-relocatable now because we have to emit the vector table anyway because the processor doesn't have 64 bit displacement.
As Nate Eldredge points out, compiling with -no-pie yields a non-relocatable binary, and I have verified the expected start address appears.

How to check which symbols on my shared library have non-position independent code (PIC)?

I'm trying to build a .deb package with debuild -i -us -uc -b and in the end I see:
Now running lintian...
warning: the authors of lintian do not recommend running it with root privileges!
W: libluajit-5.1-2: hardening-no-relro usr/lib/powerpc64le-linux-gnu/libluajit-5.1.so.2.1.0
E: libluajit-5.1-2: shlib-with-non-pic-code usr/lib/powerpc64le-linux-gnu/libluajit-5.1.so.2.1.0
W: luajit: hardening-no-relro usr/bin/luajit-2.1.0-alpha
W: luajit: binary-without-manpage usr/bin/luajit-2.1.0-alpha
Finished running lintian.
I have a hunch that I failed to define a "PIC code setup", which must be at the beginning of each external function:
The following code might appear in a PIC code setup sequence to compute
the distance from a function entry point to the TOC base:
addis 2,12,.TOC.-func#ha
addi 2,2,.TOC.-func#l
as specified by the ABI, page 99.
However I couldn't find the symbols which were non-PIC. Or maybe some relevant file that was not compiled with -fPIC?
Info:
system architecture: ppc64le
compiling .so library with: gcc -shared -fPIC
To find which symbols made your elf non-PIC/PIE (Position Independent Code/Executable), use scanelf from pax-utils package (on ubuntu, install it with sudo apt-get install pax-utils):
$ scanelf -qT /usr/local/lib/libluajit-5.1.so.2.1.0 | head -n 3
libluajit-5.1.so.2.1.0: buf_grow [0x7694] in (optimized out: previous lj_BC_MODVN) [0x7600]
libluajit-5.1.so.2.1.0: buf_grow [0x769C] in (optimized out: previous lj_BC_MODVN) [0x7600]
libluajit-5.1.so.2.1.0: buf_grow [0x76A0] in (optimized out: previous lj_BC_MODVN) [0x7600]
$ objdump -Sa /usr/local/lib/libluajit-5.1.so.2.1.0 | grep -A5 \ 7694:
7694: 00 00 80 39 li r12,0
7698: c6 07 8c 79 rldicr r12,r12,32,31
769c: 00 00 8c 65 oris r12,r12,0
76a0: 00 00 8c 61 ori r12,r12,0
76a4: a6 03 89 7d mtctr r12
76a8: 21 04 80 4e bctrl
On my case an absolute address was meant to be load on r12, but that's not possible for a dynamic library, so the linker used 0 for that parameter (I had to use #GOT operator, but that's the particular solution to my case).
On the luajit program, it's possible to define the address on linking time and it looks like this:
1003d0d4: 00 00 80 39 li r12,0
1003d0d8: c6 07 8c 79 rldicr r12,r12,32,31
1003d0dc: 07 10 8c 65 oris r12,r12,4103
1003d0e0: 30 ca 8c 61 ori r12,r12,51760
1003d0e4: a6 03 89 7d mtctr r12
Quite different right?
a much detailed explanation can be found on this wonderful Gentoo wiki page.
The failing lintian check is this:
# Now that we're sure this is really a shared library, report on
# non-PIC problems.
if ($objdump->{$cur_file}->{TEXTREL}) {
tag 'shlib-with-non-pic-code', $cur_file;
}
So you can probably find the offending file by looking for a .o that contains a TEXTREL dynamic section (which is making its way into your final link).
To do this, you can use readelf --dyanamic, in something like the following:
find . -name '*.o' |
while read obj
do
if readelf --dynamic "$obj" | grep -q TEXTREL
then
echo "$obj contains a TEXTREL section"
fi
done

Meanings of mips flags from readelf command?

I have executed the command "readelf -h test" ("test" is my binary program) on linux, and got following text:
ELF header:
Magic: 7f 45 4c 46 ....
Data: 2's complement, little endian
...
**Flags: 0x1007, noreorder, pic, cpic, o32, mips1**
...
Could you please let me know each meanings of flags of the above text in detail?
I have googled it, but could not find answers. Any comments would be appreciated.
ELF header flags are architecture-specific. For MIPS they are defined in SYSTEM V APPLICATION BINARY INTERFACE
EF_MIPS_NOREORDER 0x00000001
EF_MIPS_PIC 0x00000002
EF_MIPS_CPIC 0x00000004
EF_MIPS_ARCH 0xf0000000

What does "echo 1 > rom" for PCI devices do, and how can I do it programatically?

I am trying to write a program to dump option/expansion ROMs on linux. I already have the necessary PCI port IO to get an expansion ROM's base address out of the PCI configuration data at offset 0x30 and make it enabled, but when I try to access the base in memory I get a segfault. So I am trying to understand what is happening when you do the "echo 1 > rom" from a linux command line, since after that the rom seems plenty accessible (see here for a little more context: http://etherboot.org/wiki/romdumping)
E.g. let's say I do the following:
lspci
01:00.0 VGA compatible controller: ATI Technologies Inc RV370 5B60 [Radeon X300 (PCIE)]
cd /sys/bus/pci/devices/0000:01:00.0
lspci -x -v -s 01:00.0
01:00.0 VGA compatible controller: ATI Technologies Inc RV370 5B60 [Radeon X300 (PCIE)]
Subsystem: ATI Technologies Inc Device 0402
Flags: bus master, fast devsel, latency 0, IRQ 27
Memory at d0000000 (32-bit, prefetchable) [size=128M]
I/O ports at dc00 [size=256]
Memory at dfde0000 (32-bit, non-prefetchable) [size=64K]
Expansion ROM at dfe00000 [disabled] [size=128K]
Capabilities: [50] Power Management version 2
Capabilities: [58] Express Endpoint, MSI 00
Capabilities: [80] Message Signalled Interrupts: Mask- 64bit+ Queue=0/0 Enable+
Capabilities: [100] Advanced Error Reporting <?>
Kernel driver in use: radeon
Kernel modules: radeonfb, radeon
00: 02 10 60 5b 07 04 10 00 00 00 00 03 10 00 80 00
10: 08 00 00 d0 01 dc 00 00 00 00 de df 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 02 10 02 04
30: 00 00 e0 df 50 00 00 00 00 00 00 00 0b 01 00 00
Note the line that says "Expansion ROM at dfe00000 [disabled] [size=128K]"
Now per the PCI spec I can see that the bottom bit should be set to 1 to enable the expansion ROM, so I did a read and write back of 0xdfe00001, and then I get
01:00.0 VGA compatible controller: ATI Technologies Inc RV370 5B60 [Radeon X300 (PCIE)]
Subsystem: ATI Technologies Inc Device 0402
Flags: bus master, fast devsel, latency 0, IRQ 27
Memory at d0000000 (32-bit, prefetchable) [size=128M]
I/O ports at dc00 [size=256]
Memory at dfde0000 (32-bit, non-prefetchable) [size=64K]
Expansion ROM at dfe00000 [size=128K]
Capabilities: [50] Power Management version 2
Capabilities: [58] Express Endpoint, MSI 00
Capabilities: [80] Message Signalled Interrupts: Mask- 64bit+ Queue=0/0 Enable+
Capabilities: [100] Advanced Error Reporting <?>
Kernel driver in use: radeon
Kernel modules: radeonfb, radeon
00: 02 10 60 5b 07 04 10 00 00 00 00 03 10 00 80 00
10: 08 00 00 d0 01 dc 00 00 00 00 de df 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 02 10 02 04
30: 01 00 e0 df 50 00 00 00 00 00 00 00 0b 01 00 00
(note the 0x01 at offset 0x30 and the line now saying "Expansion ROM at dfe00000 [size=128K]").
But I can't access 0xdfe00000. Meanwhile, when O do the "echo 1 > rom" in the command line, it does NOT change the line to remove the "disabled", and really it doesn't make any change at all to the output of lspci. So what is the "echo 1 > rom" doing that I'm not, which makes it subsequently possible to do the "dd if=rom of=/tmp/rom"?
Much appreciated
I've tried to get the exROM contents from an NVidia VGA board (NVS310) - from the Linux command line :-)
This is what I did, approximately:
From lspci -vvn, I found out that my board is at 0000:02:00.0 and its exROM is at 0xf7000000 size 512 kB (and its address decoder is disabled in the exROM BAR = via bit 0 in PCI config space reg #c0 == offset 0x30).
I then used setpci to toggle that "exROM BAR enable bit" in the PCI config space. Notice the notation value:mask in the "write" form of setpci:
setpci --dumpregs
setpci -s 0000:02:00.0 ROM_ADDRESS
setpci -s 0000:02:00.0 ROM_ADDRESS=00000001:00000001
setpci -s 0000:02:00.0 ROM_ADDRESS
lspci -vvn -s 0000:02:00.0
dd if=/dev/mem of=vgabios.bin bs=64k skip=63232 count=8
Which resulted in some semi-plausible looking binary data in a file 512 kB long.
Access via /sys/bus/pci/devices/0000:02:00.0/rom did not work, even after I wrote a "1" into that pseudo-file.
rom is a special file usually read-protected unless '1' is written to it, from sysfs-pci.txt:
The 'rom' file is special in that it provides read-only access to the device's
ROM file, if available. It's disabled by default, however, so applications
should write the string "1" to the file to enable it before attempting a read
call, and disable it following the access by writing "0" to the file. Note
that the device must be enabled for a rom read to return data successfully.
In the event a driver is not bound to the device, it can be enabled using the
'enable' file, documented above.
So it looks like 'echo 1 > rom' really only enables reading the rom through sysfs.
Maybe you can't access the rom through its bar because it's not mapped to dfe00000 by default? Not sure, worth checking though.
sudo echo 1 >rom for me (a zsh user) outputs permission denied: rom and the same seems to be the case when using bash, when using su and then typing echo 1 >rom works. If you are scripting you may need to thus do sudo su -c 'echo 1 >rom' or pkexec --keep-cwd su -c 'echo 1 >rom'. Perhaps it can also depend on your system (security) configuration. All I can say in that regard is that I use arch linux, without mitigations and linux-zen 5.19

How can I get the architecture of a '.a' file?

I have a .a file from which I want to get architecture information. Running file myFile.a results in file.a: current ar archive. How can I get more information on what architecture the file contains?
You can also skip the ar command and use readelf, via something like:
readelf -h <archive>.a | grep 'Class\|File\|Machine'
[00:32:15] /usr/lib $ readelf -h libxslt.a | grep 'Class\|File\|Machine'
File: libxslt.a(attrvt.o)
Class: ELF32
Machine: Intel 80386
File: libxslt.a(xslt.o)
Class: ELF32
Machine: Intel 80386
... #Trimmed this, it goes on a bit
File: libxslt.a(transform.o)
Class: ELF32
Machine: Intel 80386
File: libxslt.a(security.o)
Class: ELF32
Machine: Intel 80386
[00:32:24] /usr/lib $
In case it's relevant, here's the other information that you can get from readelf -h. I just trimmed the above with grep, obviously:
File: libxslt.a(security.o)
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: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 2548 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 16
Section header string table index: 13
That output is for one of the object files in libxslt.a, but it gives the same information for each file.
Use
lipo -info libExample.a
It will Who the architecture it build for. Other functions like otool or file doesn't give the exact answer and sometimes it to verbose to get the correct information.
objdump is another option:
objdump -a file.a|grep 'file format'
http://linux.die.net/man/1/ar
extract the object files from the archive and inspect them with file(1), nm(1), etc.
I would suggest using objdump instead of lipo. objdump provides detailed information than lipo.

Resources