15

I'm running Linux Mint 14 with qemu, qemu-user, and the gnueabi toolchain installed. I compiled test.c with arm-linux-gnueabi-gcc test.c -o test.

When I try and run qemu-arm /usr/arm-linux-gnueabi/lib/ld-linux.so.3 test

I get an error saying: test: error while loading shared libraries: test: cannot open shared object file: No such file or directory. Running qemu-arm test, as I've previously tried, gives /lib/ld-linux.so.3: No such file or directory

However, the file does exist and is reachable.

$ stat /usr/arm-linux-gnueabi/lib/ld-linux.so.3
  File: `/usr/arm-linux-gnueabi/lib/ld-linux.so.3' -> `ld-2.15.so'
  Size: 10          Blocks: 0          IO Block: 4096   symbolic link
Device: 801h/2049d  Inode: 4083308     Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2013-04-22 16:19:48.090613901 -0700
Modify: 2012-09-21 08:31:29.000000000 -0700
Change: 2013-04-22 15:58:41.042542851 -0700
 Birth: -

Does anyone know how I can make qemu run an arm program without having to emulate an entire arm Linux kernel?

test.c is

#include <stdio.h>
int main() {
    printf("this had better work\n");
}

and file test is

test: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.31, BuildID[sha1]=0xf2e49db65394b77c77ee5b65b83c0cc9220cbfc0, not stripped
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
David
  • 2,080
  • 5
  • 29
  • 44
  • 4
    if running without an OS, printf is the last thing you want to do, certainly not the first program you want to write for that system. turn on an led which doesnt make sense on qemu, but jamming a character out the serial port/uart to the serial terminal is usually something trivial. Also you would want to start with an assembly program not C as the bootstrap code is also not trivial as you have to make sure you understand the memory map, where the program is loaded, etc. – old_timer Apr 23 '13 at 17:01
  • This comes from the arm libraries not being installed as system libraries (even if they're installed as target libraries for the cross compiler). If the distribution supports it then you can install arm as a multiarch target (like how x86 and x86_64 are supported simultaneously). In Ubuntu speak that's something like `apt-add-architecture arm && apt-get install libc6:arm`. I don't know mint. Just compile with `-static` if you don't want to think about it. – sh1 Sep 15 '17 at 21:00

6 Answers6

31

you can run the example by providing a path to the arm-linux-gnueabi shared libs using the -L flag.

qemu-arm -L /usr/arm-linux-gnueabi/

also make sure the LD_LIBRARY_PATH is not set.

unset LD_LIBRARY_PATH
vivek_v
  • 411
  • 3
  • 3
15
$ export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi

This works for me. It's basically the same thing as:

$ qemu-arm -L /usr/arm-linux-gnueabi/

You can add it to the ~/.bashrc file so you don't have to type it everytime you open the terminal.

Mita_
  • 753
  • 1
  • 7
  • 10
12

I also met this problem when running a C program with assembly code. My solution is to build the executable with the option "-static", for instance

arm-linux-gnueabi-gcc -static -g main.c square.s

Then

qemu-arm a.out

will not report the error saying "can not find the /lib/ld-linux.so.3".

The only drawback is that the executable could be with a large size. But it's helpful when you just want to test your code.

Of course, you can go with the method from Balau(see artless noise's answer). But if you don't want to feel frustrated by something like "UART serial ports" in this step, which is only to run a simple "test" function, go for a try of my fix.

Ning
  • 189
  • 1
  • 10
  • Dude! It's 2018 and your solution works for me. Care to elaborate how that `-static` works like a charm? – J. Doe Sep 03 '18 at 18:39
  • @J.Doe Stumbled upon this so I thought I should elaborate. I have been compiling using the `-static` flag for a while now. It works because when cross-compiling using this flag, all the dependencies are compiled into the executable itself, and not left for the linker to resolve. When you run the resulting executable on another machine (`qemu-arm` in this case), there are no unresolved dependencies, and hence it _works like a charm_. – agdhruv Apr 24 '19 at 14:08
  • @agdhruv, it's 2019 and I logged back into this account after a long time. Your answer is only 3 days old. =)) – J. Doe Apr 27 '19 at 14:54
5

I solved the problem by copying the following libraries into /lib but I believe there should be a way better solution rather than this nasty solution I invented!

sudo cp  /usr/arm-linux-gnueabi/lib/ld-linux.so.3 /lib
sudo cp /usr/arm-linux-gnueabi/lib/libgcc_s.so.1 /lib
sudo cp /usr/arm-linux-gnueabi/lib/libc.so.6 /lib

Please let me know if there are other better solutions as I am interested to know.

Mona Jalal
  • 34,860
  • 64
  • 239
  • 408
  • 3
    Yes of course this will work, but you need to run Linux in this case. The original question wanted to **avoid** Linux. You didn't copy the libraries and run a *qemu* virtual machine without a Linux kernel? That seems impossible. – artless noise May 25 '13 at 14:37
  • I found the -L /usr/arm-linux-gnueabihf/ option to qemu-arm to work, as suggested above... – muman Sep 25 '15 at 05:24
  • @artlessnoise, there's nothing wrong, here. This answer makes the libraries visible to qemu so the emulated binary will link. It's not booting an emulated Linux system. It's still using syscall emulation. – sh1 Sep 15 '17 at 20:37
  • @artlessnoise, that's what qemu [does](https://people.debian.org/~ballombe/qemu.sarge/qemu.html/ch1.htm)]. First it has to be able to link the ARM binary against ARM libraries (unless it's static), then those libraries make system calls and qemu traps those system calls and translates then to the host OS. It's much more efficient than having to emulate an entire ARM Linux kernel. This solution simply moves libraries to a place where qemu can find them. Those libraries still have to make system calls for anything interesting to happen. – sh1 Sep 21 '17 at 16:32
  • @sh1 Right, but the ARM syscall interface is not the same as the x86. Some things don't exist on one that do on the other. qemu must do this translation or in some cases implement it; which may not be possible as it needs direct access to Linux internals. It seems less buggy to use an arm-none compiler. Again, it depends on what you are trying to achieve. I didn't say this doesn't work in all cases. However, it has trade-offs to other solutions. – artless noise Sep 21 '17 at 19:41
1

If you want to run ARM without Linux, then you need a different compiler (at least). arm-linux-gnueabi-gcc is a compiler for Linux. The compiler and libc are intimately linked. You will need a newlib compiler with a portability layer for qemu.porting newlib

See: Balau and Google newlib+qemu. A newlib port is hosted at Github and seems to the same as the Balau blog.

Typically a non-Linux gcc is called arm-none-eabi-gcc. The prefix arm-none-eabi- is recognized by some configure scripts.

artless noise
  • 21,212
  • 6
  • 68
  • 105
  • 2
    if you want to make system calls it matters, for bare metal work that doesnt require system calls you can for the most part use arm-linux-gnueabi or arm-none-eabi flavors of toolchain. – old_timer Apr 23 '13 at 14:35
  • 1
    http://github.com/dwelch67/yagbat has a qemu directory, I am working on a separate qemu bare metal example repo, but dont have anything to publish yet. – old_timer Apr 23 '13 at 14:36
  • @dwelch Right, you can compiler with `-nostdlib` too, but then you have to code your own library and the `libgcc` stuff. For example, when you *divide by zero*, the *Linux* version of `libgcc` does something different than `newlib` (which resets, I think). I think this poster is better off with a *newlib* gcc, but you are correct you could use the `arm-linux-gnueabi-gcc` compiler if you are careful. This route is likely to get a lot of random linker/loader errors which are often not easy to figure out. – artless noise Apr 23 '13 at 14:57
  • The key to your answer is "portability layer for qemu" that is a big deal. Any old arm-none-eabi will not work if you make system calls. But if you dont make system calls then any arm-linux-gnueabi or arm-none-eabi will work as a compiler, and to reinforce that you use -nostdlib, etc...if you can build your own or find a newlib for the platform then definitely go with arm-none-eabi. – old_timer Apr 23 '13 at 16:59
0

A variant, which worked for me, was to pass the loader library directly and to specify the required library paths using the loader parameter --library-path. For example:

$ TOOLCHAIN_ROOT=/usr/local/gcc-linaro-arm-linux-gnueabihf-4.7-2013.03-20130313_linux/arm-linux-gnueabihf
$ qemu-arm $TOOLCHAIN_ROOT/libc/lib/ld-linux-armhf.so.3 --library-path $TOOLCHAIN_ROOT/libc/lib/arm-linux-gnueabihf:/$TOOLCHAIN_ROOT/lib ./my_executable

Or equivalently export LD_LIBRARY_PATH instead of using --library-path.

nucleon
  • 1,128
  • 1
  • 6
  • 19