qemu-arm running compiled binary - c

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.

Related

How to preload library with ld_preload to wine(windows game)?

I want to learn how to preload and hook functions in wine running windows apps.
I'm trying to preload a library with ld_preload to wine(windows game(32-bit)) on Arch Linux (64-bit but I think I installed 32-bit support). I get the error wrong ELF class: ELFCLASS32 and the same for ELFCLASS64.
Full error text:
"ERROR: ld.so: object './eve.so' from LD_PRELOAD cannot be preloaded
(wrong ELF class: ELFCLASS32): ignored."
the same for 64bit and another one
ERROR: ld.so: object './eve.so' from LD_PRELOAD cannot be preloaded
(cannot open shared object file): ignored.
How am I getting "wrong class" when I have both 32 and 64-bit installed? What architecture do I need to make it work right?
Wow.exe:
Wow.exe: PE32 executable (GUI) Intel 80386, for MS Windows
I tried to build with and without the -m32 flag ( I changed all uint32 to uint64):
gcc -std=c99 -Wall -Werror -m32 -O0 -fpic -shared -ldl -lGL -o eve.so eve.c
I saw this answer:
ltrace /lib/ld-linux.so.2 --preload /path/to/lib/strcmp.so ./exec
But don't know how to run it with wine running the app.
I want to learn how to preload and hook functions in wine running windows apps. I saw this guide:
https://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/276206-linux-simple-injection-ld_preload.html
The wrong ELF class: ELFCLASS32 means you are trying to inject a 32-bit program into a 64-bit process. This would lead me to believe your game is 64-bit, and you should compile your libraries as 64-bit as well. But since you mention you saw the error for 64-bits as well, it would be best to check your wine installation directly. Run pacman -Q --info wine to check.
The second error message you reported, cannot open shared object file, means the dynamic linker can't find your library. Double check all your file paths. Instead of using the relative import ./eve.so, use a full absolute path (/path/to/lib/eve.so) so there's no ambiguity to the system. You usually want to specify an absolute path to LD_PRELOAD. The reason is that it being an environment variable, it's inherited by child processes - which may have a different working directory than the parent process. So any relative path would fail to locate the library to preload.
As for how to set the environment variable in Wine, wine passes on the entire shell environment variable space to the Windows environment variable space, so you just set the variable in Linux beforehand and it will be available to the game inside wine:
export LD_PRELOAD=/path/to/lib/eve.so
wine ...
As another note, LD_PRELOAD will affect the wine loader only. If you would like to affect wineserver as well:
wineserver -k
export LD_PRELOAD=...
wine ...
Finally, see this post for more details if this still isn't working for you, it's a more in depth explanation of how to do injection into wine specifically.

Program cannot load shared library GCC

First things first, here is the error message:
./Game: error while loading shared libraries: libEngine.so: cannot open shared object file: No such file or directory
There was no problems while compiling.
Library directories passed to GCC while compiling Game: -L../../bin -L.
Directory tree:
ENGINE
-bin
--Game (executable)
--libEngine.so
-Game
--src
---source code + Game makefile
-Engine
--src
---source code + shared library makefile
I can provide more info on demand.
Setting LD_LIBRARY_PATH is a possible, but usually not the best solution. In particular, dependence on environment produces programs which work for you, but not for your coworkers or your professor (because their environment is different).
Adding -rpath=/path/to/bin to the link line eliminates the need to muck with environment.
Even better: -rpath='$ORIGIN' lets you move the entire installation directory to a different place, and the program will still find its shared libraries in its own bin/ directory.

Does a .so library need to be present at run time in all cases

My question is in relation to .so shared libraries. I am building a project that uses cmake on one ubuntu machine but running the application on another ubuntu machine.
In the CMakeLists.txt file, I have the following lines:
project (clientapp)
add_executable(${PROJECT_NAME} ${SOURCES} ${WAKAAMA_SOURCES} ${SHARED_SOURCES})
LINK_DIRECTORIES(/home/user//mraa-master-built/build/src)
target_link_libraries (clientapp libmraa.so)
target_link_libraries(clientapp m)
These lines add two libraries libmraa.so and the math library to the executable and it runs successfully on the other machine.
My understanding of shared libraries is that they must be present at compile time, and when the application starts. But I do not have the libmraa.so file on the other machine and the application runs ok. I expected it not to work.
Is my assumption correct?
In general, gcc and clang support lazy linking/binding of symbols, but not for entire libraries. This means that all of the shared objects (ie: .so files) should be present at application startup, at a minimum. The one exception to this is if you modified your makefile to not link against these libraries, and you manually call library functions via dlopen()/dlsym(), etc.
The binding of individual symbols within those libraries can be postponed until they are needed, or you can force all the symbols to be resolved at startup, using -z lazy or -z now, respectively.
It is strange that your application runs without libmraa.so being present. The two most likely reasons your application is running in the absence of the library is:
Your application isn't using any symbols defined in the library, so the linker ignores the library at build time (try ldd app_name and see if your library is present in the list of libraries provided by ldd).
Something is amiss in your build script, and you are statically linking against a .a archive of the library.
Edit: In response to how the application knows how to find the library, your linker (ld in this case) will use rpath lookup to decide which directories to use in its search for the appropriate library. You can see how this works by doing something like LD_DEBUG=libs app_name from the command line. You can also add an extra path via LD_LIBRARY_PATH=/some/path app_name.
Is my assumption correct?
Yes.
There are two likely explanations for why the application runs anyway:
You are mistaken, and there is libmraa.so somewhere on the machine (though perhaps not in the place where you looked), or
Your compiler defaults to -Wl,--as-needed by default, and your binary does not in fact depend on libmraa.so despite the fact that it appears on your link line.
You can trivially confirm or disprove either of the above guesses.
To confirm guess 2, do this:
readelf -d clientapp | grep NEED | grep libmraa
# if there is no output, guess 2 is correct
If guess 2 is wrong, to confirm guess 1, do this (on machine without libmrra.so):
ldd clientapp | grep libmraa.so
# if guess 2 is incorrect, and this command produces no output, then
# your dynamic loader is broken, which is very unlikely.

Cross compiling for Raspberry pi 2 error

I wanted to start cross compiling for raspberry pi2 on Ubuntu 32bit (in virtual box), so I downloaded the toolchain on the github site (https://github.com/raspberrypi/tools) and tried to compile a simple hello world program with the command (I've included the path to the bin folder that contains arm-linux-gnueabihf-gcc-4.8.3 to the PATH variable.):
arm-linux-gnueabihf-gcc-4.8.3 HelloWorld.c
However, I always get the following error message:
path/to/the/linker/in/the/toolchain/ld:/path/to/the/libc.so.6file/in/the/toolchain/libc.so.6: file format not recognized; treating as linker script
and subsequently a syntax error.
When I look into libc.so.6, I see a single line containing:
libc-2.13.so
The libc-2.13.so file is present in the same folder as the libc.so.6 file. When I invoke
file libc-2.13.so
I get:
libc-2.13.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), BuildID[sha1]=dbd0cdca5a677bea1417be1272f4c5ef43bd3e22, for GNU/Linux 2.6.26, stripped
I don't know what could cause this error since obviously the linker from the toolchain and the libc.so.6 file from the toolchain are processed so the file format should be recognized, right?
Can someone point me in the right direction here? Thanks!
I will suggest you alternate way to do Cross compilation. I tried it and it works. You can use crosstool-NG. It gives you graphical way to setup your toolchain for cross compilation. There are lot of option for setting up toolchain. You can explore that.
Now you are doing for ARM-RPi but tomorrow if your Target CPU changed then it will be very easy to reconfigure the toolchain again.
You can find easy steps given in this article. I hope this works for you.
When I look into libc.so.6, I see a single line containing:
libc-2.13.so
I just ran into this.
The problem is way simpler than you think. When you un-gz'd and untar'd the toolchain, what happened is that libc.so.6 became a text file. It is supposed to be a "symbolic link" file pointing at the correct file "libc-2.13.so".
If you are using windows and 7-Zip, make sure to click "Run AS Administrator" when you start 7-zip. If you simply drag and drop, the error is not so obvious.
In my first effort, I had to include the path to gcc in the command. Then I just compiled programs on the RPi.
~/toolchain/raspbian-toolchain-gcc-4.7.2-linux32/bin/arm-linux-gnueabihf-gcc whets.c

Error when using libraries in C

I'm trying to play an mp3 file in terminal using C and I followed this link to do so.
I've installed the two libraries libmpg123 and libao. Also, I've compiled the play.c program using the command:
gcc -O2 -o play play.c -lmpg123 -lao
But I get the following error when I run it:
./play: error while loading shared libraries: libao.so.4: cannot open shared object file: No such file or directory
Can you figure it out why it happened.
The executable can be linked, but at run-time, it cannot find the shared libraries. Add the libraries to your LD_LIBRARY_PATH so the program can find them at run time.

Resources