Hello, not being the maintainer I just found it interesting to investigate...
This message seems to be printed while it wants to load libc.so.6 into the process, and is just printed if there is not yet a "/etc/ld.so.cache". Then it has a handling to be able to load some hardware optimized versions of libc.so.6. Unfortunately there is a problem assembling the path to that file - it just creates "/lib/i386-linux-gnu/" instead of "/lib/i386-linux-gnu/libc.so.6": export QEMU_STRACE=1 $ mv /etc/ld.so.cache /etc/ld.so.cache.renamed # just do this in a test environment! qemu-i386-static /home/buster-chroot-i386/bin/true 12023 brk(NULL) = 0x4000a000 12023 uname(0x4080a97a) = 0 12023 access("/etc/ld.so.nohwcap",F_OK) = -1 errno=2 (No such file or directory) 12023 access("/etc/ld.so.preload",R_OK) = -1 errno=2 (No such file or directory) 12023 openat(AT_FDCWD,"/etc/ld.so.cache",O_RDONLY|O_CLOEXEC) = -1 errno=2 (No such file or directory) 12023 openat(AT_FDCWD,"/lib/i386-linux-gnu/",O_RDONLY|O_CLOEXEC) = 3 12023 read(3,0x4080a6f0,512) = -1 errno=21 (Is a directory) 12023 close(3) = 0 12023 writev(2,0x4080a360,0xa)/home/buster-chroot-i386/bin/true: error while loading shared libraries: b/i38/-li6ux-nnu/g: nnca rotd ealefiat dlib/i38/-li6ux-nnu/g: o = 137 12023 exit_group(127) This can be tracked down to that stack, where some temporary arrays get filled: 53 movsw 20: x/i $pc => 0x4082679a <mempcpy+26>: movsw %ds:(%esi),%es:(%edi) 21: /x *0x40833c70 = 0x74 (gdb) nexti 54 2: rep 20: x/i $pc => 0x4082679c <mempcpy+28>: rep movsl %ds:(%esi),%es:(%edi) 21: /x *0x40833c70 = 0x6c74 Running on native shows here 0x736c74 -> means a difference of "tl" to "tls". Therefore fails to assemble later something like "/lib/i386-linux-gnu/tls/i686/sse2/libc.so.6" (gdb) bt #0 mempcpy () at ../sysdeps/i386/i686/mempcpy.S:54 #1 0x4081a26d in _dl_important_hwcaps (platform=<optimized out>, platform_len=4, sz=0x40832b4c <ncapstr>, max_capstrlen=0x40832b48 <max_capstrlen>) at dl-hwcaps.c:275 #2 0x40813883 in _dl_init_paths (llp=0x0) at dl-load.c:691 #3 0x4080eb61 in dl_main (phdr=0x40000034, phnum=11, user_entry=0x4080ad1c, auxv=0x4080ae00) at rtld.c:1323 #4 0x40823651 in _dl_sysdep_start (start_argptr=0x4080adc0, dl_main=0x4080d410 <dl_main>) at ../elf/dl-sysdep.c:253 #5 0x4080cfdf in _dl_start_final (arg=0x4080adc0) at rtld.c:414 #6 _dl_start (arg=<optimized out>) at rtld.c:521 #7 0x4080c25b in _start () from /lib/ld-linux.so.2 That movsw instruction, or at least that mempcpy seems to not working correctly in qemu-i386 on armel hardware. I could reproduce on a 3.16.0-4-kirkwood kernel with - armel qemu-i386 2.12.0 inside a buster chroot - armel qemu-i386-static 2.0.0 Unfoturnately I had trouble to run qemu-i386-static 1.7.0 and 1.5.0. Attached some more notes and a minimal static test program showing that issue. Kind regards, Bernhard
# lscpu Architecture: armv5tel Byte Order: Little Endian CPU(s): 1 On-line CPU(s) list: 0 Thread(s) per core: 1 Core(s) per socket: 1 Socket(s): 1 Model name: Feroceon 88FR131 rev 1 (v5l) root@nas3c3b5d:/home/bernhard/910571-qemu# cat /proc/cpuinfo processor : 0 model name : Feroceon 88FR131 rev 1 (v5l) BogoMIPS : 1191.93 Features : swp half thumb fastmult edsp CPU implementer : 0x56 CPU architecture: 5TE CPU variant : 0x2 CPU part : 0x131 CPU revision : 1 Hardware : QNAP TS-119/TS-219 Revision : 0000 Serial : 0000000000000000 su - cat /etc/debian_version # 8.8 apt install qemu-user-static mkdir /home/bernhard/910571-qemu -p cd /home/bernhard/910571-qemu debootstrap --arch=armel buster buster-chroot-armel http://192.168.178.25:9999/debian-otherarch-deb.debian.org/ chroot buster-chroot-armel # edit /etc/apt/sources.list.d/... deb http://192.168.178.25:9999/debian-otherarch-deb.debian.org buster main deb-src http://192.168.178.25:9999/debian-otherarch-deb.debian.org buster main deb http://192.168.178.25:9999/debian-otherarch-debug.mirrors.debian.org buster-debug main contrib non-free # edit /etc/inputrc - history search apt install debootstrap file strace gdb dpkg-dev qemu-user-static qemu-user-static-dbgsym mkdir /home/qemu-source/orig -p cd /home/qemu-source/orig apt source qemu-user-static cd mkdir /home/buster-chroot-i386/usr/bin -p cp -a /usr/bin/qemu-i386-static /home/buster-chroot-i386/usr/bin/ mv /usr/bin/arch-test /usr/bin/arch-test.orig debootstrap --arch=i386 buster /home/buster-chroot-i386 http://192.168.178.25:9999/debian-10-buster-deb.debian.org/ ... W: Failure trying to run: chroot "/home/buster-chroot-i386" /bin/true W: See /home/buster-chroot-i386/debootstrap/debootstrap.log for details cat /home/buster-chroot-i386/debootstrap/debootstrap.log ... chroot: failed to run command '/bin/true': Exec format error chroot /home/buster-chroot-i386 /bin/true /bin/true: error while loading shared libraries: b/i38/-li6ux-nnu/g: nnca rotd ealefiat dlib/i38/-li6ux-nnu/g: o export QEMU_STRACE=1 chroot /home/buster-chroot-i386 /bin/true 11734 brk(NULL) = 0x4000a000 11734 uname(0x4080a9ba) = 0 11734 access("/etc/ld.so.nohwcap",F_OK) = -1 errno=2 (No such file or directory) 11734 access("/etc/ld.so.preload",R_OK) = -1 errno=2 (No such file or directory) 11734 openat(AT_FDCWD,"/etc/ld.so.cache",O_RDONLY|O_CLOEXEC) = -1 errno=2 (No such file or directory) 11734 openat(AT_FDCWD,"/lib/i386-linux-gnu/",O_RDONLY|O_CLOEXEC) = 3 11734 read(3,0x4080a730,512) = -1 errno=21 (Is a directory) 11734 close(3) = 0 11734 writev(2,0x4080a3a0,0xa)/bin/true: error while loading shared libraries: b/i38/-li6ux-nnu/g: nnca rotd ealefiat dlib/i38/-li6ux-nnu/g: o = 113 11734 exit_group(127) unset QEMU_STRACE dpkg --add-architecture i386 apt update apt install busybox:i386 file /bin/busybox /bin/busybox: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=56e29dd08978b9aaccd89ab8884fbd6e8750d547, stripped qemu-i386-static /bin/busybox Inconsistency detected by ld.so: dl-version.c: 205: _dl_check_map_versions: Assertion `needed != NULL' failed! file /home/buster-chroot-i386/bin/true /home/buster-chroot-i386/bin/true: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=702a162597a95a7f39dd315313bed8cf1a5c50d2, stripped qemu-i386-static /home/buster-chroot-i386/bin/true Inconsistency detected by ld.so: dl-version.c: 205: _dl_check_map_versions: Assertion `needed != NULL' failed! export QEMU_STRACE=1 qemu-i386-static /home/buster-chroot-i386/bin/true 11972 brk(NULL) = 0x4000a000 11972 uname(0x4080a97a) = 0 11972 access("/etc/ld.so.nohwcap",F_OK) = -1 errno=2 (No such file or directory) 11972 access("/etc/ld.so.preload",R_OK) = -1 errno=2 (No such file or directory) 11972 openat(AT_FDCWD,"/etc/ld.so.cache",O_RDONLY|O_CLOEXEC) = 3 11972 fstat64(3,0x4080a5c0) = 0 11972 mmap2(NULL,13855,PROT_READ,MAP_PRIVATE,3,0) = 0x40836000 11972 close(3) = 0 11972 openat(AT_FDCWD,"/lib/i386-linux-gnu/libc.so.6",O_RDONLY|O_CLOEXEC) = 3 11972 read(3,0x4080a6f0,512) = 512 11972 fstat64(3,0x4080a620) = 0 11972 mmap2(NULL,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x4083a000 11972 mmap2(NULL,1940000,PROT_READ,MAP_PRIVATE|MAP_DENYWRITE,3,0) = 0x4083c000 11972 mprotect(0x40855000,1814528,PROT_NONE) = 0 11972 mmap2(0x40855000,1359872,PROT_EXEC|PROT_READ,MAP_PRIVATE|MAP_DENYWRITE|MAP_FIXED,3,0x19) = 0x40855000 11972 mmap2(0x409a1000,450560,PROT_READ,MAP_PRIVATE|MAP_DENYWRITE|MAP_FIXED,3,0x165) = 0x409a1000 11972 mmap2(0x40a10000,12288,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_DENYWRITE|MAP_FIXED,3,0x1d3) = 0x40a10000 11972 mmap2(0x40a13000,10784,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x40a13000 11972 close(3) = 0 11972 writev(2,0x4080a7a0,0xa)Inconsistency detected by ld.so: dl-version.c: 205: _dl_check_map_versions: Assertion `needed != NULL' failed! = 111 11972 exit_group(127) mv /etc/ld.so.cache /etc/ld.so.cache.renamed qemu-i386-static /home/buster-chroot-i386/bin/true 12023 brk(NULL) = 0x4000a000 12023 uname(0x4080a97a) = 0 12023 access("/etc/ld.so.nohwcap",F_OK) = -1 errno=2 (No such file or directory) 12023 access("/etc/ld.so.preload",R_OK) = -1 errno=2 (No such file or directory) 12023 openat(AT_FDCWD,"/etc/ld.so.cache",O_RDONLY|O_CLOEXEC) = -1 errno=2 (No such file or directory) 12023 openat(AT_FDCWD,"/lib/i386-linux-gnu/",O_RDONLY|O_CLOEXEC) = 3 12023 read(3,0x4080a6f0,512) = -1 errno=21 (Is a directory) 12023 close(3) = 0 12023 writev(2,0x4080a360,0xa)/home/buster-chroot-i386/bin/true: error while loading shared libraries: b/i38/-li6ux-nnu/g: nnca rotd ealefiat dlib/i38/-li6ux-nnu/g: o = 137 12023 exit_group(127) . mount -t proc proc /home/bernhard/910571-qemu/buster-chroot-armel/proc gdb -q --args qemu-i386-static /home/buster-chroot-i386/bin/true set height 0 set width 0 set pagination off directory /home/qemu-source/orig/qemu-2.12+dfsg b print_openat run b/i38/-li6ux-nnu/g: nnca rotd ealefiat dlib/i38/-li6ux-nnu/g: o 38/ili6-x-nuu/gn: nnoa retd fale iatadlib/i38/-li6ux-nnu/g: o /lib/i386-linux-gnu/ /lib /i38 6-li nux- gnu/ lib/ i38/ -li6 ux-n nu/g lib/i38/-li6ux-nnu/g lib/i38/-li6ux-nnu/g . Assuming that the problem is that "openat(AT_FDCWD,"/lib/i386-linux-gnu/",O_RDONLY|O_CLOEXEC)" just points to a directory. Therefore trying to debug: buster-chroot-armel: qemu-i386-static -strace -g 50000 /home/buster-chroot-i386/bin/true buster-i386 VM: gdb -q /bin/true directory /root/libc6/orig/glibc-2.27/elf set height 0 set width 0 set pagination off target remote nas3c3b5d:50000 (gdb) b open Breakpoint 2 at 0x408259d0: file ../sysdeps/unix/sysv/linux/open.c, line 33. (gdb) cont Continuing. Breakpoint 2, __libc_open (file=0x40828d9b "/etc/ld.so.cache", oflag=524288) at ../sysdeps/unix/sysv/linux/open.c:33 33 { (gdb) cont Continuing. Breakpoint 2, __libc_open (file=0x4080a590 "/lib/i386-linux-gnu/", oflag=524288) at ../sysdeps/unix/sysv/linux/open.c:33 33 { (gdb) bt #0 __libc_open (file=0x4080a590 "/lib/i386-linux-gnu/", oflag=524288) at ../sysdeps/unix/sysv/linux/open.c:33 #1 0x408122b4 in open_verify (name=name@entry=0x4080a590 "/lib/i386-linux-gnu/", fbp=fbp@entry=0x4080a6dc, loader=loader@entry=0x40833940, whatcode=64, mode=0, found_other_class=0x4080a6d3, free_name=false, fd=-1) at dl-load.c:1723 #2 0x40812a8c in open_path (name=name@entry=0x4000054d "libc.so.6", namelen=namelen@entry=10, mode=mode@entry=0, sps=0x40832b40 <rtld_search_dirs>, realname=0x4080a6d4, fbp=0x4080a6dc, loader=0x40833940, whatcode=<optimized out>, found_other_class=0x4080a6d3) at dl-load.c:2052 #3 0x408141cb in _dl_map_object (loader=0x40833940, name=<optimized out>, type=1, trace_mode=0, mode=0, nsid=<optimized out>) at dl-load.c:2382 #4 0x40818f54 in openaux (a=0x4080aab8) at dl-deps.c:63 #5 0x408245e3 in _dl_catch_exception (exception=0x4080aaac, operate=0x40818f20 <openaux>, args=0x4080aab8) at dl-error-skeleton.c:196 #6 0x40819186 in _dl_map_object_deps (map=<optimized out>, preloads=<optimized out>, npreloads=<optimized out>, trace_mode=<optimized out>, open_mode=<optimized out>) at dl-deps.c:249 #7 0x4080f27c in dl_main (phdr=<optimized out>, phnum=<optimized out>, user_entry=<optimized out>, auxv=<optimized out>) at rtld.c:1726 #8 0x40823651 in _dl_sysdep_start (start_argptr=0x4080adc0, dl_main=0x4080d410 <dl_main>) at ../elf/dl-sysdep.c:253 #9 0x4080cfdf in _dl_start_final (arg=0x4080adc0) at rtld.c:414 #10 _dl_start (arg=<optimized out>) at rtld.c:521 #11 0x4080c25b in _start () from /lib/ld-linux.so.2 (gdb) list dl-load.c:1999,2060 1999 static int 2000 open_path (const char *name, size_t namelen, int mode, 2001 struct r_search_path_struct *sps, char **realname, 2002 struct filebuf *fbp, struct link_map *loader, int whatcode, 2003 bool *found_other_class) 2004 { 2005 struct r_search_path_elem **dirs = sps->dirs; 2006 char *buf; 2007 int fd = -1; 2008 const char *current_what = NULL; 2009 int any = 0; 2010 2011 if (__glibc_unlikely (dirs == NULL)) 2012 /* We're called before _dl_init_paths when loading the main executable 2013 given on the command line when rtld is run directly. */ 2014 return -1; 2015 2016 buf = alloca (max_dirnamelen + max_capstrlen + namelen); 2017 do 2018 { 2019 struct r_search_path_elem *this_dir = *dirs; 2020 size_t buflen = 0; 2021 size_t cnt; 2022 char *edp; 2023 int here_any = 0; 2024 int err; 2025 2026 /* If we are debugging the search for libraries print the path 2027 now if it hasn't happened now. */ 2028 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS) 2029 && current_what != this_dir->what) 2030 { 2031 current_what = this_dir->what; 2032 print_search_path (dirs, current_what, this_dir->where); 2033 } 2034 2035 edp = (char *) __mempcpy (buf, this_dir->dirname, this_dir->dirnamelen); 2036 for (cnt = 0; fd == -1 && cnt < ncapstr; ++cnt) 2037 { 2038 /* Skip this directory if we know it does not exist. */ 2039 if (this_dir->status[cnt] == nonexisting) 2040 continue; 2041 2042 buflen = 2043 ((char *) __mempcpy (__mempcpy (edp, capstr[cnt].str, 2044 capstr[cnt].len), 2045 name, namelen) 2046 - buf); 2047 2048 /* Print name we try if this is wanted. */ 2049 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) 2050 _dl_debug_printf (" trying file=%s\n", buf); 2051 2052 fd = open_verify (buf, -1, fbp, loader, whatcode, mode, 2053 found_other_class, false); 2054 if (this_dir->status[cnt] == unknown) 2055 { 2056 if (fd != -1) 2057 this_dir->status[cnt] = existing; 2058 /* Do not update the directory information when loading 2059 auditing code. We must try to disturb the program as 2060 little as possible. */ (gdb) x/50xc 0x4080a590 0x4080a590: 47 '/' 108 'l' 105 'i' 98 'b' 47 '/' 105 'i' 51 '3' 56 '8' 0x4080a598: 54 '6' 45 '-' 108 'l' 105 'i' 110 'n' 117 'u' 120 'x' 45 '-' 0x4080a5a0: 103 'g' 110 'n' 117 'u' 47 '/' 0 '\000' 47 '/' 116 't' 108 'l' 0x4080a5a8: 56 '8' 0 '\000' 105 'i' 54 '6' 101 'e' 50 '2' 115 's' 115 's' 0x4080a5b0: 0 '\000' 0 '\000' 0 '\000' 108 'l' 98 'b' 0 '\000' 108 'l' 105 'i' 0x4080a5b8: 111 'o' 99 'c' 46 '.' 115 's' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0x4080a5c0: 0 '\000' 0 '\000' -> "/lib/i386-linux-gnu/\0/tl\0ie2ss\0\0\0lb\0\lioc.s\0" ??? (gdb) x/15xc capstr[0].str 0x40833c70: 116 't' 108 'l' 0 '\000' 47 '/' 105 'i' 54 '6' 56 '8' 0 '\000' 0x40833c78: 115 's' 115 's' 101 'e' 50 '2' 0 '\000' 47 '/' 116 't' But should be: 1: buf = 0xbffff580 "/lib/i386-linux-gnu/tls/i686/sse2/libc.so.6" (gdb) print capstr[0] $5 = {str = 0xb7fffef0 "tls/i686/sse2/tls/sse2/", len = 14} (gdb) list dl-hwcaps.c:38,400 38 /* Return an array of useful/necessary hardware capability names. */ 39 const struct r_strlenpair * 40 _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, 41 size_t *max_capstrlen) 42 { 43 uint64_t hwcap_mask = GET_HWCAP_MASK(); 44 /* Determine how many important bits are set. */ 45 uint64_t masked = GLRO(dl_hwcap) & hwcap_mask; 46 size_t cnt = platform != NULL; 47 size_t n, m; 48 size_t total; 49 struct r_strlenpair *temp; 50 struct r_strlenpair *result; 51 struct r_strlenpair *rp; 52 char *cp; 53 54 /* Count the number of bits set in the masked value. */ 55 for (n = 0; (~((1ULL << n) - 1) & masked) != 0; ++n) 56 if ((masked & (1ULL << n)) != 0) 57 ++cnt; 58 59 #ifdef NEED_DL_SYSINFO_DSO 60 /* The system-supplied DSO can contain a note of type 2, vendor "GNU". 61 This gives us a list of names to treat as fake hwcap bits. */ 62 63 const char *dsocaps = NULL; 64 size_t dsocapslen = 0; 65 if (GLRO(dl_sysinfo_map) != NULL) 66 { 67 const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr; 68 const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum; 69 for (uint_fast16_t i = 0; i < phnum; ++i) 70 if (phdr[i].p_type == PT_NOTE) 71 { 72 const ElfW(Addr) start = (phdr[i].p_vaddr 73 + GLRO(dl_sysinfo_map)->l_addr); 74 /* NB: Some PT_NOTE segment may have alignment value of 0 75 or 1. gABI specifies that PT_NOTE segments should be 76 aligned to 4 bytes in 32-bit objects and to 8 bytes in 77 64-bit objects. As a Linux extension, we also support 78 4 byte alignment in 64-bit objects. If p_align is less 79 than 4, we treate alignment as 4 bytes since some note 80 segments have 0 or 1 byte alignment. */ 81 ElfW(Addr) align = phdr[i].p_align; 82 if (align < 4) 83 align = 4; 84 else if (align != 4 && align != 8) 85 continue; 86 /* The standard ELF note layout is exactly as the anonymous struct. 87 The next element is a variable length vendor name of length 88 VENDORLEN (with a real length rounded to ElfW(Word)), followed 89 by the data of length DATALEN (with a real length rounded to 90 ElfW(Word)). */ 91 const struct 92 { 93 ElfW(Word) vendorlen; 94 ElfW(Word) datalen; 95 ElfW(Word) type; 96 } *note = (const void *) start; 97 while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz) 98 { 99 /* The layout of the type 2, vendor "GNU" note is as follows: 100 .long <Number of capabilities enabled by this note> 101 .long <Capabilities mask> (as mask >> _DL_FIRST_EXTRA). 102 .byte <The bit number for the next capability> 103 .asciz <The name of the capability>. */ 104 if (note->type == NT_GNU_HWCAP 105 && note->vendorlen == sizeof "GNU" 106 && !memcmp ((note + 1), "GNU", sizeof "GNU") 107 && note->datalen > 2 * sizeof (ElfW(Word)) + 2) 108 { 109 const ElfW(Word) *p 110 = ((const void *) note 111 + ELF_NOTE_DESC_OFFSET (sizeof "GNU", align)); 112 cnt += *p++; 113 ++p; /* Skip mask word. */ 114 dsocaps = (const char *) p; /* Pseudo-string "<b>name" */ 115 dsocapslen = note->datalen - sizeof *p * 2; 116 break; 117 } 118 note = ((const void *) note 119 + ELF_NOTE_NEXT_OFFSET (note->vendorlen, 120 note->datalen, align)); 121 } 122 if (dsocaps != NULL) 123 break; 124 } 125 } 126 #endif 127 128 /* For TLS enabled builds always add 'tls'. */ 129 ++cnt; 130 131 if (__access_noerrno ("/etc/ld.so.nohwcap", F_OK) == 0) 132 { 133 /* If hwcap is disabled, we only have the base directory to search. */ 134 result = (struct r_strlenpair *) malloc (sizeof (*result)); 135 if (result == NULL) 136 goto no_memory; 137 138 result[0].str = (char *) result; /* Does not really matter. */ 139 result[0].len = 0; 140 141 *sz = 1; 142 return result; 143 } 144 145 /* Create temporary data structure to generate result table. */ 146 temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp)); 147 m = 0; 148 #ifdef NEED_DL_SYSINFO_DSO 149 if (dsocaps != NULL) 150 { 151 /* dsocaps points to the .asciz string, and -1 points to the mask 152 .long just before the string. */ 153 const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1]; 154 GLRO(dl_hwcap) |= (uint64_t) mask << _DL_FIRST_EXTRA; 155 /* Note that we add the dsocaps to the set already chosen by the 156 LD_HWCAP_MASK environment variable (or default HWCAP_IMPORTANT). 157 So there is no way to request ignoring an OS-supplied dsocap 158 string and bit like you can ignore an OS-supplied HWCAP bit. */ 159 hwcap_mask |= (uint64_t) mask << _DL_FIRST_EXTRA; 160 #if HAVE_TUNABLES 161 TUNABLE_SET (glibc, tune, hwcap_mask, uint64_t, hwcap_mask); 162 #else 163 GLRO(dl_hwcap_mask) = hwcap_mask; 164 #endif 165 size_t len; 166 for (const char *p = dsocaps; p < dsocaps + dsocapslen; p += len + 1) 167 { 168 uint_fast8_t bit = *p++; 169 len = strlen (p); 170 171 /* Skip entries that are not enabled in the mask word. */ 172 if (__glibc_likely (mask & ((ElfW(Word)) 1 << bit))) 173 { 174 temp[m].str = p; 175 temp[m].len = len; 176 ++m; 177 } 178 else 179 --cnt; 180 } 181 } 182 #endif 183 for (n = 0; masked != 0; ++n) 184 if ((masked & (1ULL << n)) != 0) 185 { 186 temp[m].str = _dl_hwcap_string (n); 187 temp[m].len = strlen (temp[m].str); 188 masked ^= 1ULL << n; 189 ++m; 190 } 191 if (platform != NULL) 192 { 193 temp[m].str = platform; 194 temp[m].len = platform_len; 195 ++m; 196 } 197 198 temp[m].str = "tls"; 199 temp[m].len = 3; 200 ++m; 201 202 assert (m == cnt); 203 204 /* Determine the total size of all strings together. */ 205 if (cnt == 1) 206 total = temp[0].len + 1; 207 else 208 { 209 total = temp[0].len + temp[cnt - 1].len + 2; 210 if (cnt > 2) 211 { 212 total <<= 1; 213 for (n = 1; n + 1 < cnt; ++n) 214 total += temp[n].len + 1; 215 if (cnt > 3 216 && (cnt >= sizeof (size_t) * 8 217 || total + (sizeof (*result) << 3) 218 >= (1UL << (sizeof (size_t) * 8 - cnt + 3)))) 219 _dl_signal_error (ENOMEM, NULL, NULL, 220 N_("cannot create capability list")); 221 222 total <<= cnt - 3; 223 } 224 } 225 226 /* The result structure: we use a very compressed way to store the 227 various combinations of capability names. */ 228 *sz = 1 << cnt; 229 result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total); 230 if (result == NULL) 231 { 232 no_memory: 233 _dl_signal_error (ENOMEM, NULL, NULL, 234 N_("cannot create capability list")); 235 } 236 237 if (cnt == 1) 238 { 239 result[0].str = (char *) (result + *sz); 240 result[0].len = temp[0].len + 1; 241 result[1].str = (char *) (result + *sz); 242 result[1].len = 0; 243 cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len); 244 *cp = '/'; 245 *sz = 2; 246 *max_capstrlen = result[0].len; 247 248 return result; 249 } 250 251 /* Fill in the information. This follows the following scheme 252 (indices from TEMP for four strings): 253 entry #0: 0, 1, 2, 3 binary: 1111 254 #1: 0, 1, 3 1101 255 #2: 0, 2, 3 1011 256 #3: 0, 3 1001 257 This allows the representation of all possible combinations of 258 capability names in the string. First generate the strings. */ 259 result[1].str = result[0].str = cp = (char *) (result + *sz); 260 #define add(idx) \ 261 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1); 262 if (cnt == 2) 263 { 264 add (1); 265 add (0); 266 } 267 else 268 { 269 n = 1 << (cnt - 1); 270 do 271 { 272 n -= 2; 273 274 /* We always add the last string. */ 275 add (cnt - 1); 276 277 /* Add the strings which have the bit set in N. */ 278 for (m = cnt - 2; m > 0; --m) 279 if ((n & (1 << m)) != 0) 280 add (m); 281 282 /* Always add the first string. */ 283 add (0); 284 } 285 while (n != 0); 286 } 287 #undef add 288 289 /* Now we are ready to install the string pointers and length. */ 290 for (n = 0; n < (1UL << cnt); ++n) 291 result[n].len = 0; 292 n = cnt; 293 do 294 { 295 size_t mask = 1 << --n; 296 297 rp = result; 298 for (m = 1 << cnt; m > 0; ++rp) 299 if ((--m & mask) != 0) 300 rp->len += temp[n].len + 1; 301 } 302 while (n != 0); 303 304 /* The first half of the strings all include the first string. */ 305 n = (1 << cnt) - 2; 306 rp = &result[2]; 307 while (n != (1UL << (cnt - 1))) 308 { 309 if ((--n & 1) != 0) 310 rp[0].str = rp[-2].str + rp[-2].len; 311 else 312 rp[0].str = rp[-1].str; 313 ++rp; 314 } 315 316 /* The second half starts right after the first part of the string of 317 the corresponding entry in the first half. */ 318 do 319 { 320 rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1; 321 ++rp; 322 } 323 while (--n != 0); 324 325 /* The maximum string length. */ 326 *max_capstrlen = result[0].len; 327 328 return result; 329 } (gdb) print temp[0] $59 = {str = 0x408329a4 <_rtld_global_ro+164> "sse2", len = 4} (gdb) print temp[1] $60 = {str = 0x40829199 "i686", len = 4} (gdb) print temp[2] $61 = {str = 0x40828a34 "tls", len = 3} (gdb) print temp[3] $62 = {str = 0x4080aaa8 "\370\252\200@\203\070\201@\231\221\202@\004", len = 1082236215} --> temp looks still quite similar between working and failing processes. (gdb) target remote nas3c3b5d:50000 Remote debugging using nas3c3b5d:50000 Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug/.build-id/d3/4d111ccc131067fcbc126906e01374c678c06e.debug...done. done. 0x4080c250 in _start () from /lib/ld-linux.so.2 warning: Unable to display "result[0]": No symbol "result" in current context. warning: Unable to display "result[1]": No symbol "result" in current context. warning: Unable to display "result[2]": No symbol "result" in current context. 14: x/i $pc => 0x4080c250 <_start>: mov %esp,%eax 16: /x *0x40833c70 = 0x0 (gdb) cont Continuing. Breakpoint 7, _dl_important_hwcaps (platform=<optimized out>, platform_len=4, sz=0x40832b4c <ncapstr>, max_capstrlen=0x40832b48 <max_capstrlen>) at dl-hwcaps.c:229 warning: Source file is more recent than executable. 229 result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total); 14: x/i $pc => 0x4081a1d2 <_dl_important_hwcaps+1218>: sub $0xc,%esp 16: /x *0x40833c70 = 0x0 (gdb) undisp 14 (gdb) undisp 16 (gdb) display result[0] 17: result[0] = <error: value has been optimized out> (gdb) display result[1] 18: result[1] = <error: value has been optimized out> (gdb) display result[2] 19: result[2] = <error: value has been optimized out> (gdb) display/i $pc 20: x/i $pc => 0x4081a1d2 <_dl_important_hwcaps+1218>: sub $0xc,%esp (gdb) next 228 *sz = 1 << cnt; 17: result[0] = <error: value has been optimized out> 18: result[1] = <error: value has been optimized out> 19: result[2] = <error: value has been optimized out> 20: x/i $pc => 0x4081a1d5 <_dl_important_hwcaps+1221>: mov %edi,%eax (gdb) 229 result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total); 17: result[0] = <error: value has been optimized out> 18: result[1] = <error: value has been optimized out> 19: result[2] = <error: value has been optimized out> 20: x/i $pc => 0x4081a1e3 <_dl_important_hwcaps+1235>: mov %ebx,%ecx (gdb) 230 if (result == NULL) 17: result[0] = <error: value has been optimized out> 18: result[1] = <error: value has been optimized out> 19: result[2] = <error: value has been optimized out> 20: x/i $pc => 0x4081a1fa <_dl_important_hwcaps+1258>: add $0x10,%esp (gdb) 229 result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total); 17: result[0] = <error: value has been optimized out> 18: result[1] = <error: value has been optimized out> 19: result[2] = <error: value has been optimized out> 20: x/i $pc => 0x4081a1ff <_dl_important_hwcaps+1263>: mov %eax,-0x40(%ebp) (gdb) 230 if (result == NULL) 17: result[0] = {str = 0x0, len = 0} 18: result[1] = {str = 0x0, len = 0} 19: result[2] = {str = 0x0, len = 0} 20: x/i $pc => 0x4081a202 <_dl_important_hwcaps+1266>: mov -0x58(%ebp),%ecx (gdb) 259 result[1].str = result[0].str = cp = (char *) (result + *sz); 17: result[0] = {str = 0x0, len = 0} 18: result[1] = {str = 0x0, len = 0} 19: result[2] = {str = 0x0, len = 0} 20: x/i $pc => 0x4081a20b <_dl_important_hwcaps+1275>: mov -0x40(%ebp),%edx (gdb) 262 if (cnt == 2) 17: result[0] = {str = 0x40833c70 "", len = 0} 18: result[1] = {str = 0x40833c70 "", len = 0} 19: result[2] = {str = 0x0, len = 0} 20: x/i $pc => 0x4081a22b <_dl_important_hwcaps+1307>: cmp $0x2,%ebx (gdb) 279 if ((n & (1 << m)) != 0) 17: result[0] = {str = 0x40833c70 "", len = 0} 18: result[1] = {str = 0x40833c70 "", len = 0} 19: result[2] = {str = 0x0, len = 0} 20: x/i $pc => 0x4081a237 <_dl_important_hwcaps+1319>: mov %edx,-0x68(%ebp) (gdb) 275 add (cnt - 1); 17: result[0] = {str = 0x40833c70 "", len = 0} 18: result[1] = {str = 0x40833c70 "", len = 0} 19: result[2] = {str = 0x0, len = 0} 20: x/i $pc => 0x4081a258 <_dl_important_hwcaps+1352>: sub $0x4,%esp (gdb) 272 n -= 2; 17: result[0] = {str = 0x40833c70 "", len = 0} 18: result[1] = {str = 0x40833c70 "", len = 0} 19: result[2] = {str = 0x0, len = 0} 20: x/i $pc => 0x4081a265 <_dl_important_hwcaps+1365>: sub $0x2,%edi (gdb) 275 add (cnt - 1); 17: result[0] = {str = 0x40833c70 "", len = 0} 18: result[1] = {str = 0x40833c70 "", len = 0} 19: result[2] = {str = 0x0, len = 0} 20: x/i $pc => 0x4081a268 <_dl_important_hwcaps+1368>: call 0x40826780 <mempcpy> (gdb) display/x *0x40833c70 21: /x *0x40833c70 = 0x0 (gdb) stepi mempcpy () at ../sysdeps/i386/i686/mempcpy.S:40 40 movl LEN(%esp), %ecx 20: x/i $pc => 0x40826780 <mempcpy>: mov 0xc(%esp),%ecx 21: /x *0x40833c70 = 0x0 (gdb) nexti 41 movl %edi, %eax 20: x/i $pc => 0x40826784 <mempcpy+4>: mov %edi,%eax 21: /x *0x40833c70 = 0x0 (gdb) 43 movl DEST(%esp), %edi 20: x/i $pc => 0x40826786 <mempcpy+6>: mov 0x4(%esp),%edi 21: /x *0x40833c70 = 0x0 (gdb) 44 movl %esi, %edx 20: x/i $pc => 0x4082678a <mempcpy+10>: mov %esi,%edx 21: /x *0x40833c70 = 0x0 (gdb) 46 movl SRC(%esp), %esi 20: x/i $pc => 0x4082678c <mempcpy+12>: mov 0x8(%esp),%esi 21: /x *0x40833c70 = 0x0 (gdb) 47 cld 20: x/i $pc => 0x40826790 <mempcpy+16>: cld 21: /x *0x40833c70 = 0x0 (gdb) 48 shrl $1, %ecx 20: x/i $pc => 0x40826791 <mempcpy+17>: shr %ecx 21: /x *0x40833c70 = 0x0 (gdb) 49 jnc 1f 20: x/i $pc => 0x40826793 <mempcpy+19>: jae 0x40826796 <mempcpy+22> 21: /x *0x40833c70 = 0x0 (gdb) info reg eax 0x2 2 ecx 0x1 1 edx 0x10 16 ebx 0x40833000 1082339328 esp 0x4080a9ec 0x4080a9ec ebp 0x4080aaa8 0x4080aaa8 esi 0x40828a34 1082296884 edi 0x40833c70 1082342512 eip 0x40826793 0x40826793 <mempcpy+19> eflags 0x203 [ CF IF ] cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x2b 43 (gdb) nexti 50 movsb 20: x/i $pc => 0x40826795 <mempcpy+21>: movsb %ds:(%esi),%es:(%edi) 21: /x *0x40833c70 = 0x0 (gdb) info reg eax 0x2 2 ecx 0x1 1 edx 0x10 16 ebx 0x40833000 1082339328 esp 0x4080a9ec 0x4080a9ec ebp 0x4080aaa8 0x4080aaa8 esi 0x40828a34 1082296884 edi 0x40833c70 1082342512 eip 0x40826795 0x40826795 <mempcpy+21> eflags 0x203 [ CF IF ] cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x2b 43 (gdb) nexti 51 1: shrl $1, %ecx 20: x/i $pc => 0x40826796 <mempcpy+22>: shr %ecx 21: /x *0x40833c70 = 0x74 (gdb) nexti 52 jnc 2f 20: x/i $pc => 0x40826798 <mempcpy+24>: jae 0x4082679c <mempcpy+28> 21: /x *0x40833c70 = 0x74 (gdb) info reg eax 0x2 2 ecx 0x0 0 edx 0x10 16 ebx 0x40833000 1082339328 esp 0x4080a9ec 0x4080a9ec ebp 0x4080aaa8 0x4080aaa8 esi 0x40828a35 1082296885 edi 0x40833c71 1082342513 eip 0x40826798 0x40826798 <mempcpy+24> eflags 0x247 [ CF PF ZF IF ] cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x2b 43 (gdb) nexti 53 movsw 20: x/i $pc => 0x4082679a <mempcpy+26>: movsw %ds:(%esi),%es:(%edi) 21: /x *0x40833c70 = 0x74 (gdb) nexti 54 2: rep 20: x/i $pc => 0x4082679c <mempcpy+28>: rep movsl %ds:(%esi),%es:(%edi) 21: /x *0x40833c70 = 0x6c74 (gdb) bt #0 mempcpy () at ../sysdeps/i386/i686/mempcpy.S:54 #1 0x4081a26d in _dl_important_hwcaps (platform=<optimized out>, platform_len=4, sz=0x40832b4c <ncapstr>, max_capstrlen=0x40832b48 <max_capstrlen>) at dl-hwcaps.c:275 #2 0x40813883 in _dl_init_paths (llp=0x0) at dl-load.c:691 #3 0x4080eb61 in dl_main (phdr=0x40000034, phnum=11, user_entry=0x4080ad1c, auxv=0x4080ae00) at rtld.c:1323 #4 0x40823651 in _dl_sysdep_start (start_argptr=0x4080adc0, dl_main=0x4080d410 <dl_main>) at ../elf/dl-sysdep.c:253 #5 0x4080cfdf in _dl_start_final (arg=0x4080adc0) at rtld.c:414 #6 _dl_start (arg=<optimized out>) at rtld.c:521 #7 0x4080c25b in _start () from /lib/ld-linux.so.2 0x6c74 -> Should be -> 0x736c74 -> Means we copied just "tl" instead of "tls" (gdb) disassemble mempcpy Dump of assembler code for function mempcpy: 0xb7ff2780 <+0>: mov 0xc(%esp),%ecx 0xb7ff2784 <+4>: mov %edi,%eax 0xb7ff2786 <+6>: mov 0x4(%esp),%edi 0xb7ff278a <+10>: mov %esi,%edx 0xb7ff278c <+12>: mov 0x8(%esp),%esi 0xb7ff2790 <+16>: cld 0xb7ff2791 <+17>: shr %ecx 0xb7ff2793 <+19>: jae 0xb7ff2796 <mempcpy+22> 0xb7ff2795 <+21>: movsb %ds:(%esi),%es:(%edi) 0xb7ff2796 <+22>: shr %ecx 0xb7ff2798 <+24>: jae 0xb7ff279c <mempcpy+28> 0xb7ff279a <+26>: movsw %ds:(%esi),%es:(%edi) => 0xb7ff279c <+28>: rep movsl %ds:(%esi),%es:(%edi) 0xb7ff279e <+30>: xchg %eax,%edi 0xb7ff279f <+31>: mov %edx,%esi 0xb7ff27a1 <+33>: ret End of assembler dump. (gdb) x/8xb 0xb7ff279a 0xb7ff279a <mempcpy+26>: 0x66 0xa5 0xf3 0xa5 0x97 0x89 0xd6 0xc3 (gdb) list ../sysdeps/i386/i686/mempcpy.S:38,62 38 ENTRY (__mempcpy) 39 40 movl LEN(%esp), %ecx 41 movl %edi, %eax 42 cfi_register (edi, eax) 43 movl DEST(%esp), %edi 44 movl %esi, %edx 45 cfi_register (esi, edx) 46 movl SRC(%esp), %esi 47 cld 48 shrl $1, %ecx 49 jnc 1f 50 movsb 51 1: shrl $1, %ecx 52 jnc 2f 53 movsw 54 2: rep 55 movsl 56 xchgl %edi, %eax 57 cfi_restore (edi) 58 movl %edx, %esi 59 cfi_restore (esi) 60 61 ret 62 END (__mempcpy)
/* bernhard@rechner:~$ uname -a Linux rechner 4.18.0-1-amd64 #1 SMP Debian 4.18.6-1 (2018-09-06) x86_64 GNU/Linux bernhard@rechner:~$ gcc -m32 -g -O0 -static 910571_test.c -o 910571_test */ #define _GNU_SOURCE #include <string.h> #include <stdio.h> int main(void) { static const char source[] = "123456"; char dest[20]; for (int i = 0; i < sizeof(dest); i++) dest[i] = 0; mempcpy(dest, source, 3); //printf("%s\n", dest); /* do not rely on printf here */ for (int i = 0; i < sizeof(dest); i++) printf("%c", dest[i]); printf("\n"); } /* On amd64/i386: bernhard@rechner:~$ ./910571_test 123 bernhard@rechner:~$ qemu-i386-static 910571_test 123 bernhard@rechner:~$ qemu-i386-static --version qemu-i386 version 2.12.0 (Debian 1:2.12+dfsg-3) bernhard@rechner:~$ uname -a Linux rechner 4.18.0-1-amd64 #1 SMP Debian 4.18.6-1 (2018-09-06) x86_64 GNU/Linux On armel: root@nas3c3b5d:/home# qemu-i386-static 910571_test 12 root@nas3c3b5d:/home# qemu-i386-static --version qemu-i386 version 2.12.0 (Debian 1:2.12+dfsg-3) root@nas3c3b5d:/home# uname -a Linux nas3c3b5d 3.16.0-4-kirkwood #1 Debian 3.16.43-2+deb8u1 (2017-06-18) armv5tel GNU/Linux ------------ wget http://snapshot.debian.org/archive/debian/20140724T221350Z/pool/main/q/qemu/qemu-user-static_2.0.0%2Bdfsg-7_armel.deb dpkg -x qemu-user-static_2.0.0+dfsg-7_armel.deb 2.0.0+dfsg-7 root@nas3c3b5d:/home/old-versions# 2.0.0+dfsg-7/usr/bin/qemu-i386-static ../910571_test 12 ------------ wget http://snapshot.debian.org/archive/debian/20140413T223847Z/pool/main/q/qemu/qemu-user-static_1.7.0%2Bdfsg-9_armel.deb dpkg -x qemu-user-static_1.7.0+dfsg-9_armel.deb 1.7.0+dfsg-9 root@nas3c3b5d:/home/old-versions# 1.7.0+dfsg-9/usr/bin/qemu-i386-static ../910571_test FATAL: kernel too old qemu: uncaught target signal 6 (Aborted) - core dumped Aborted ------------ wget http://snapshot.debian.org/archive/debian/20130724T214723Z/pool/main/q/qemu/qemu-user-static_1.5.0%2Bdfsg-5_armel.deb dpkg -x qemu-user-static_1.5.0+dfsg-5_armel.deb 1.5.0+dfsg-5 root@nas3c3b5d:/home/old-versions# 1.5.0+dfsg-5/usr/bin/qemu-i386-static ../910571_test FATAL: kernel too old qemu: uncaught target signal 6 (Aborted) - core dumped Aborted */