fmarques.org

Debugging x86 containers with Docker Desktop for Apple Sillicon

· fred

Recently I was trying to find an issue with ldd and a x86 Linux binary inside a Docker container. Problem is, if you’re using Docker, strace is not supported by default. In this article, Julia Evans explains very well why it doesn’t work and what you can do to make it happen, also including updated information on recent versions of Docker supporting the ptrace system. If you’re using the M1 (ARM) Apple chip to run x86 containers, you’re out of luck, because Docker Desktop uses QEMU to emulate the x86 architecture. When running strace, you’ll get the message:

warning: ptrace: Function not implemented

I recently found out that you can enable system calls through QEMU, similar to strace. When using docker run, just enable it by using the QEMU_STRACE env variable. Example:

docker run -e QEMU_STRACE=1 -i amd64/bash

You should be seeing something like:

 arch_prctl(4098,274904529736,136818691501592568,274904529216,274903948064,465) = 0
1 set_tid_address(274904530832,274904529736,136818691501592568,274904529216,0,465) = 1
1 brk(NULL) = 0x00000040000cc000
1 brk(0x00000040000ce000) = 0x00000040000ce000
1 mmap(0x00000040000cc000,4096,PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x00000040000cc000
1 mprotect(0x0000004001960000,4096,PROT_READ) = 0
1 mprotect(0x00000040000c7000,16384,PROT_READ) = 0
1 getuid() = 0
1 execve("/usr/local/sbin/bash",{"bash","/usr/local/bin/docker-entrypoint.sh","bash",NULL}) = -1 errno=2 (No such file or directory)
1 arch_prctl(4098,274904992584,136818691502055416,274904992064,274904410912,465) = 0
1 set_tid_address(274904993680,274904992584,136818691502055416,274904992064,0,465) = 1
1 brk(NULL) = 0x000000400013d000
1 brk(0x000000400013f000) = 0x000000400013f000
1 mmap(0x000000400013d000,4096,PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x000000400013d000
1 open("/etc/ld-musl-x86_64.path",O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 errno=2 (No such file or directory)
1 open("/lib/libncursesw.so.6",O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 errno=2 (No such file or directory)
1 open("/usr/local/lib/libncursesw.so.6",O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 errno=2 (No such file or directory)
1 open("/usr/lib/libncursesw.so.6",O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
1 fcntl(3,F_SETFD,1) = 0
1 fstat(3,0x000000400193d540) = 0
1 read(3,0x193d1f0,960) = 960
1 mmap(NULL,376832,PROT_READ,MAP_PRIVATE,3,0) = 0x00000040019d8000
1 mmap(0x00000040019ee000,167936,PROT_EXEC|PROT_READ,MAP_PRIVATE|MAP_FIXED,3,0x16000) = 0x00000040019ee000
1 mmap(0x0000004001a17000,94208,PROT_READ,MAP_PRIVATE|MAP_FIXED,3,0x3f000) = 0x0000004001a17000
1 mmap(0x0000004001a2e000,24576,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,3,0x55000) = 0x0000004001a2e000
1 close(3) = 0
1 mprotect(0x0000004001a2e000,20480,PROT_READ) = 0
1 mprotect(0x00000040019d1000,4096,PROT_READ) = 0
1 mprotect(0x0000004000125000,16384,PROT_READ) = 0
1 open("/dev/tty",O_RDWR|O_LARGEFILE|O_NONBLOCK) = -1 errno=6 (No such device or address)
1 ioctl(0,TIOCGWINSZ,0x000000400193d9e8) = -1 errno=25 (Not a tty)
[...]

Happy debugging!