[Bug 30134] New: Wine on ARM: .init/.text sections passed to assembler need directives to allow for mixed/pure arm32/thumb2 builds (.init section thumb2 libc ctors vs. Wine arm32 ctor)

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Mar 10 18:32:55 CST 2012


http://bugs.winehq.org/show_bug.cgi?id=30134

             Bug #: 30134
           Summary: Wine on ARM: .init/.text sections passed to assembler
                    need directives to allow for mixed/pure arm32/thumb2
                    builds (.init section thumb2 libc ctors vs. Wine arm32
                    ctor)
           Product: Wine
           Version: 1.4
          Platform: arm
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: tools
        AssignedTo: wine-bugs at winehq.org
        ReportedBy: focht at gmx.net
    Classification: Unclassified


Hello,

Wine on ARM - some food ;-)
I have some ARM machines "pets" at home, ranging from low spec ARM7TDMI
(ARMv4T) to Cortex-A8 (ARMv7-A) and Cortex-A9 MPCore dual and quad flavours -
currently considered high spec - until Cortex-A15 shows up.

The dual/quad Cortex-A9 machines which I use for work/development are running
recent 3.1/3.2 Linux kernels and distros, mostly based on Linaro builds.
Good enough to build Wine with decent speed - slower than i3/i5 multicore but
comparable to my Atom-based machines.
The difference: 3 watts (quad core A9) vs. 35 watts (dual core Atom with 4
hyperthreads) under full load (idle load ratio is even worse).

Linaro toolchains are used to build Wine, they have a default profile for
Cortex-A9 Thumb-2 NEON (CFLAGS="-gdwarf-2" was passed to Wine).

--- snip ---
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabi/4.6.1/lto-wrapper
Target: arm-linux-gnueabi
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro
4.6.1-9ubuntu3' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.6 --enable-shared --enable-linker-build-id
--with-system-zlib --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6
--libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin
--enable-objc-gc --enable-multilib --disable-sjlj-exceptions
--with-arch=armv7-a --with-float=softfp --with-fpu=vfpv3-d16 --with-mode=thumb
--disable-werror --enable-checking=release --build=arm-linux-gnueabi
--host=arm-linux-gnueabi --target=arm-linux-gnueabi
Thread model: posix
gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) 
...
$ as -v
GNU assembler version 2.21.53 (arm-linux-gnueabi) using BFD version (GNU
Binutils for Ubuntu) 2.21.53.20110810
--- snip ---

Running "wineboot" to create a fresh WINEPREFIX gives:

--- snip ---
$ wineboot
wine: created the configuration directory '/home/linaro/.wine'
fixme:seh:RtlUnwind Not implemented on ARM
err:module:attach_process_dlls "ntdll.dll" failed to initialize, aborting
err:seh:segv_handler Got unexpected trap 0
fixme:seh:RtlUnwind Not implemented on ARM
err:module:attach_process_dlls "ntdll.dll" failed to initialize, aborting
err:seh:segv_handler Got unexpected trap 0
Segmentation fault
--- snip ---

Gdb session:

--- snip ---
$ gdb wine
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
...
(gdb) run wineboot
Starting program: /home/linaro/projects/wine/wine-install/bin/wine wineboot
[Thread debugging using libthread_db enabled]
fixme:seh:RtlUnwind Not implemented on ARM
err:module:attach_process_dlls "ntdll.dll" failed to initialize, aborting
err:seh:segv_handler Got unexpected trap 0

Program received signal SIGSEGV, Segmentation fault.
0x40280000 in __wine_spec_pe_header () from
/home/linaro/projects/wine/wine-install/bin/../lib/wine/ntdll.dll.so
(gdb) bt
#0  0x40280000 in __wine_spec_pe_header () from
/home/linaro/projects/wine/wine-install/bin/../lib/wine/ntdll.dll.so
#1  0x4027182a in _init () from
/home/linaro/projects/wine/wine-install/bin/../lib/wine/ntdll.dll.so
#2  0x402de0e6 in __wine_spec_dll_entry (inst=Cannot access memory at address
0xbf2903cb
) at /home/linaro/projects/wine/wine-git/dlls/winecrt0/dll_entry.c:37
Cannot access memory at address 0xbf2903db
...
(gdb) info reg
r0             0x1    1
r1             0x407d4380    1081951104
r2             0x354    852
r3             0x0    0
r4             0xbeffe2d0    3204440784
r5             0xbeffed70    3204443504
r6             0x88c1    35009
r7             0xbf2903bf    3207136191
r8             0x0    0
r9             0x0    0
r10            0x4001e000    1073864704
r11            0x0    0
r12            0x402f6328    1076847400
sp             0x40d6fc38    0x40d6fc38
lr             0x4027182b    1076303915
pc             0x40280000    0x40280000 <__wine_spec_pe_header+59344>
cpsr           0xf0030    983088
--- snip ---

cpsr "T" bit is set so we are in thumb mode.

Disassembly of ".init" section shows thumb2 code due to toolchain defaults.

--- snip ---
(gdb) disas 0x4027182a
Dump of assembler code for function _init:
   0x40271824 <+0>:    push    {r3, lr}
   0x40271826 <+2>:    bl    0x402831c0 <call_gmon_start>
   0x4027182a <+6>:    nop
   0x4027182c <+8>:    b    0x40282830 <__wine_spec_pe_header+69632>
__wine_spec_pe_header:
...
   0x40d88604 <+69628>:    andeq    r0, r0, r0
   0x40d88608 <+69632>:    blx    0x40db3eac <__wine_spec_init_ctor>
   0x40d8860c <+69636>:    pop    {r3, pc}
--- snip ---

The long branch at 0x4027182c (part of .init section that belongs to Wine) was
assembled as 32 bit ARM code because GNU assembler will generate 32 bit ARM
code by default if not told otherwise (Wine doesn't explicitly emit directives
for sections nor passes additional options to "as") 

Before and after entering "call_gmon_start" it was thumb mode, hence no veneer
required to do a mode switch (thumb <-> arm). 

--- snip ---
$ ls -la /usr/lib/*/crt*
-rw-r--r-- 1 root root 1588 2012-03-07 05:21 /usr/lib/arm-linux-gnueabi/crt1.o
-rw-r--r-- 1 root root 1216 2012-03-07 05:21 /usr/lib/arm-linux-gnueabi/crti.o
-rw-r--r-- 1 root root  884 2012-03-07 05:21 /usr/lib/arm-linux-gnueabi/crtn.o
-rw-r--r-- 1 root root 1588 2012-03-07 05:26
/usr/lib/arm-linux-gnueabihf/crt1.o
-rw-r--r-- 1 root root 1216 2012-03-07 05:26
/usr/lib/arm-linux-gnueabihf/crti.o
-rw-r--r-- 1 root root  884 2012-03-07 05:26
/usr/lib/arm-linux-gnueabihf/crtn.o
--- snip ---

--- snip ---
$ objdump -x /usr/lib/arm-linux-gnueabi/crti.o

/usr/lib/arm-linux-gnueabi/crti.o:     file format elf32-littlearm
/usr/lib/arm-linux-gnueabi/crti.o
architecture: arm, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
private flags = 5000000: [Version5 EABI]
...
RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE 
0000000a R_ARM_THM_JUMP24  __gmon_start__
00000010 R_ARM_GOTPC       _GLOBAL_OFFSET_TABLE_
00000014 R_ARM_GOT32       __gmon_start__


RELOCATION RECORDS FOR [.init]:
OFFSET   TYPE              VALUE 
00000002 R_ARM_THM_CALL    call_gmon_start
--- snip --- 

"call_gmon_start" code from libc's initfini, obviously thumb/thumb2:

--- snip ---
$ objdump -d /usr/lib/arm-linux-gnueabi/crti.o

/usr/lib/arm-linux-gnueabi/crti.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <call_gmon_start>:
   0:    4b03          ldr    r3, [pc, #12]    ; (10 <call_gmon_start+0x10>)
   2:    4a04          ldr    r2, [pc, #16]    ; (14 <call_gmon_start+0x14>)
   4:    447b          add    r3, pc
   6:    589b          ldr    r3, [r3, r2]
   8:    b10b          cbz    r3, e <call_gmon_start+0xe>
   a:    f7ff bffe     b.w    0 <__gmon_start__>
   e:    4770          bx    lr
  10:    00000008     .word    0x00000008
  14:    00000000     .word    0x00000000

Disassembly of section .init:

00000000 <_init>:
   0:    b508          push    {r3, lr}
   2:    f7ff fffe     bl    0 <_init>
   6:    bf00          nop

Disassembly of section .fini:

00000000 <_fini>:
   0:    b508          push    {r3, lr}
   2:    bf00          nop
--- snip ---

--- snip ---
(gdb) disas
Dump of assembler code for function call_gmon_start:
   0x402831c0 <+0>:    ldr    r3, [pc, #12]    ; (0x402831d0
<call_gmon_start+16>)
   0x402831c2 <+2>:    ldr    r2, [pc, #16]    ; (0x402831d4
<call_gmon_start+20>)
   0x402831c4 <+4>:    add    r3, pc
   0x402831c6 <+6>:    ldr    r3, [r3, r2]
   0x402831c8 <+8>:    cbz    r3, 0x402831ce <call_gmon_start+14>
   0x402831ca <+10>:    b.w    0x40282cc4
=> 0x402831ce <+14>:    bx    lr
   0x402831d0 <+16>:    andeq    r2, r7, r8, lsr lr
   0x402831d4 <+20>:    andeq    r0, r0, r4, asr r3
End of assembler dump.
(gdb) info reg
r0             0x1    1
r1             0x407d4380    1081951104
r2             0x354    852
r3             0x0    0
r4             0xbeffe2d0    3204440784
r5             0xbeffed70    3204443504
r6             0x88c1    35009
r7             0x40d6fc40    1087831104
r8             0x0    0
r9             0x0    0
r10            0x4001e000    1073864704
r11            0x0    0
r12            0x402f6328    1076847400
sp             0x40d6fc38    0x40d6fc38
lr             0x4027182b    1076303915
pc             0x402831ce    0x402831ce <call_gmon_start+14>
cpsr           0x800f0030    -2146500560
--- snip ---

"bx lr" (return from subroutine): due to cpsr "T" bit already set, it will
remain in thumb mode.

--- snip ---
(gdb) si
0x4027182a in _init () from
/home/linaro/projects/wine/wine-install/bin/../lib/wine/ntdll.dll.so
(gdb) disas
Dump of assembler code for function _init:
   0x40271824 <+0>:    push    {r3, lr}
   0x40271826 <+2>:    bl    0x402831c0 <call_gmon_start>
=> 0x4027182a <+6>:    nop
   0x4027182c <+8>:    b    0x40282830 <__wine_spec_pe_header+69632>
End of assembler dump.
(gdb) info reg
r0             0x1    1
r1             0x407d4380    1081951104
r2             0x354    852
r3             0x0    0
r4             0xbeffe2d0    3204440784
r5             0xbeffed70    3204443504
r6             0x88c1    35009
r7             0x40d6fc40    1087831104
r8             0x0    0
r9             0x0    0
r10            0x4001e000    1073864704
r11            0x0    0
r12            0x402f6328    1076847400
sp             0x40d6fc38    0x40d6fc38
lr             0x4027182b    1076303915
pc             0x4027182a    0x4027182a <_init+6>
cpsr           0x800f0030    -2146500560
--- snip ---

Still in thumb mode (16 bit nop).
The next long branch was originally assembled s 32 bit ARM opcode (through
Wine's assembler invocation) and is not valid for thumb mode.

--- snip ---
(gdb) disas
Dump of assembler code for function _init:
   0x40271824 <+0>:    push    {r3, lr}
   0x40271826 <+2>:    bl    0x402831c0 <call_gmon_start>
   0x4027182a <+6>:    nop
=> 0x4027182c <+8>:    b    0x40282830 <__wine_spec_pe_header+69632>
End of assembler dump.
(gdb) si
0x4027182e in _init () from
/home/linaro/projects/wine/wine-install/bin/../lib/wine/ntdll.dll.so
--- snip ---

It's interpreted as two distinct 16 bit thumb opcodes, hence not doing as
intended (branch over 64 KiB).

Regards

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list