Objdump doesn't recognize the architecture of a shared library - arm

I built a shared library on Ubuntu 14.04 for ARM platform. The file has compiled and build successfully. I can inspect exported symbols with nm command but when I check .so file header I got the information that architecture is unknown.
Is this library built correctly, why is the library architecture unknown ?
objdump -f libMyLib.so
libMyLib.so: file format elf32-little
architecture: UNKNOWN!, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x000033a0

You need to use the objdump binary provided by the toolchain of your target system (ARM), not from host system(x86_64).
As a example: I have setup a host system Linux x86_64 targeting openwrt mips, my toolchain folder has some files:
mips-openwrt-linux-gnu-ar
mips-openwrt-linux-gnu-as
mips-openwrt-linux-gnu-gcc
mips-openwrt-linux-gnu-ld
mips-openwrt-linux-gnu-objdump
mips-openwrt-linux-gnu-nm
These are the tools to manipulate programs for openwrt mips system, so instead of just calling objdump, I need to call ./mips-openwrt-linux-gnu-objdump -f <bin file> to read and get the proper output for the compiled file.

Related

Embedding resources into executable using GCC on Arm?

I've used the following linker command to convert a TensorFlow model file myv2.tflite to "dummy" object file myv2.o, so that I can link it into an executable, to avoid having to drag this file separately:
ld --relocatable --format=binary --output=myv2.o myv2.tflite
I've done this on Ubuntu x86_64. However, I will need to do the same for Arm. I suppose I cannot reuse the same myv2.o? Do I have to regenerate the file on Arm using ld from an appropriate Arm toolchain?
I suppose I cannot reuse the same myv2.o?
You can't that; file is an ELF 64bit x86_64 ABI object file, you need it for your target architecture
Do I have to regenerate the file on Arm
no, there's no reason ld needs to run on an ARM machine,
using ld from an appropriate Arm toolchain?
exactly, just replace ld with your correctly targeting linker, e.g. arm-none-eabi-ld if this is for baremetal. Again, this is normal cross-development: no need to run on the target architecture, just build for the target architecture.

qemu-arm running compiled binary

Trying to run a compiled binary I've extracted from a firmware on qemu, however I encounter this error:
root#ubuntu14:~# qemu-arm -L /usr/arm-linux-gnueabi ~/x
/system/bin/linker: No such file or directory
root#ubuntu14:~# file ./x
./x: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), stripped
I'm using the "-L" flag, as suggested in:
qemu-arm can't run arm compiled binary
However, this flag doesn't seem to make a different for me, neither does setting QEMU_LD_PREFIX
Could it be some missing dependencies?
It looks like the system is not able to find the dynamic linker (which in your case appears to be /system/bin/linker, rather than the the normal /lib/ld-linux-armhf.so.3 or similar.
Since I don't have access to your code, I've tried to reproduce this by mounting a Raspberry Pi "Raspbian" image on /mnt on my system. If I try to run /mnt/bin/echo hello, like this:
qemu-arm /mnt/bin/echo hello
I get a similar error:
/lib/ld-linux-armhf.so.3: No such file or directory
I can provide an explicit path to the dynamic linker like this:
qemu-arm /mnt/lib/ld-linux-armhf.so.3 /mnt/bin/echo hello
Now I get a different error:
/mnt/bin/echo: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
That's actually great, because that is a normal "I can't find my shared libraries" error, and the solution is to use LD_LIBRARY_PATH. Rather than setting this in our environment, we can set this in the environment created by qemu-arm with the -E flag:
qemu-arm -E LD_LIBRARY_PATH=/mnt/lib/arm-linux-gnueabihf/ /mnt/lib/ld-linux-armhf.so.3 /mnt/bin/echo hello
Which gets me the output:
hello
I suspect that these same two techniques -- providing an explicit path to the linker, and providing an explicit library search path in LD_LIBRARY_PATH -- may help you out. Let me know how it works!
/system/bin/linker is the Android dynamic linker, so you need a directory with the Android dynamic linker and dynamic libraries, not one for Linux (which is what /usr/arm-linux-gnueabi will be). You should be able to pull the relevant files out of your firmware image, I expect.

How to compile neon on ARM

I used the
arm-linux-gnueabi-g++ test.cpp -march=armv7-a -mfloat-abi=softfp -mfpu=neon -o test
on ubantu to get an excecutable file on ARM, but when I ran
adb push ./test /data/test
adb shell
cd data
chmod 777 test
./test
I got the following error:
./system/bin/sh: ./test: No such file or directory
I was confused about this.
If you intend to run the executable on Android (as it seems), you should ideally build it using the Android NDK. The problem is that your executable links to glibc which is available on normal linux systems, but not on Android. (In detail, the executable can't start because it requires the dynamic linker /lib/ld-linux.so.3 which isn't available on Android. In addition, it also requires glibc in the form of libc.so.6.)
If you build executables using the Android NDK, it will link to the Bionic libc, which is what is available on Android.
Alternatively, if you add -static when linking (in your case, in your single compile+link command), you'll get a static executable, which should work on both normal linux and Android.

Cross-compiled application does not run on Raspberry Pi

I'm just doing my first steps with Buildroot and Raspberry Pi (running Raspbian). But somehow I seem to do something wrong with the cross compilation. The application is a most simple Hello World program written in C. This is what I did:
Downloaded and installed buildroot
make raspberrypi2_defconfig
make toolchain
Then I wrote the tiny application and the following Makefile:
CROSS_BIN := /home/me/raspi/buildroot-2016.05/output/host/usr/bin
SYSROOT := /home/me/raspi/buildroot-2016.05/output/host/usr/arm-buildroot-linux-uclibcgnueabihf/sysroot
PATH := $(CROSS_BIN):$(PATH)
CC := arm-linux-gcc
CFLAGS := --sysroot=$(SYSROOT)
app: app.c
$(CC) $(CFLAGS) -o $# $<
Compiled the app and copied it to the Raspberry. When I tried to run it, RPI complains that it can't find the file (though it's there and executable for sure). The binary type seems ok to me and should fit to the CPU:
pi#raspberrypi:~ $ ./app
-bash: ./app: No such file or directory
pi#raspberrypi:~ $ ls -l app
-rwxr-xr-x 1 pi pi 4916 Jul 10 11:07 app
pi#raspberrypi:~ $ file app
app: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, not stripped
pi#raspberrypi:~ $ lscpu
Architecture: armv7l
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
Model name: ARMv7 Processor rev 5 (v7l)
CPU max MHz: 900.0000
CPU min MHz: 600.0000
Can somebody tell me what I'm doing wrong? If I compile the app natively and run it on the development host, it runs without a problem.
My money is on /lib/ld-uClibc.so.0 missing from your Rasperry pi. Am I right?
Okay, this library is your dynamic loader, it is responsible for loading your dynamic libraries at runtime. It will load the required shared libraries into the process address space and set the appropriate permissions on the memory (read only, read write and executable).
Your cross-compiler requires a loader that does not exist, probably due to mismatch between the installed image on the RPi and the cross-compilation environment (your sysroot).
There are several ways to fix it, let's start by examining a binary that works, try file /bin/ls and post the dynamic loader here.
For example:
$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=5e052e8de057d379ab51d4af510ad9318fe77b46, stripped
When I tried to run it, RPI complains that it can't find the file (though it's there and executable for sure).
The shell is complaining that it cannot find a file in order to execute your program, not that it cannot find your file.
If it's installed use the strace command to determine what file cannot be found.
Most likely you have a dynamic library issue, e.g. you built with a uClibc toolchain, but your rootfilesystem has glibc.
Two common solutions:
(A) build your program with static linking (so that it no longer depends on the installed libraries of the target system).
$(CC) $(CFLAGS) -o -static $# $<
(B) rebuild the Buildroot toolchain to match the library that is already installed on your RPi. i.e. instead of a uClibc toolchain, build a glibc toolchain of matching version number.

How to create executable coff file from a C source

I am trying to do a simulate with Simcore Alpha/Functional Simulator and I need to create an image file but it is giving an error like "This is not Coff Executable" how can I create an Executable Coff file from a C source in linux?
In order to do this, you'll need a cross compiling gcc that is built to output COFF files. You may need to build gcc yourself if you can't find a pre-built one.
After you download gcc, you will need to configure it. The important option is --target; so if you want to target an Alpha architecture you would do:
configure --target=alpha-coff
I would also recommend you add a prefix to the binaries and install them into a different directory so you have no problems with the compiler interacting with the system compiler:
configure --target=alpha-coff --prefix=/opt/cross-gcc --program-prefix=coff-
(this will create coff-gcc in /opt/cross-gcc/bin, you can tweak those if want something different).
Linux executable format is called ELF.
COFF is a common file format for object modules, which are linked to make an ELF file or an EXE file
In your case if you have access to gcc, you can try
gcc mysource.c -o myprogram

Resources