On Wed, Nov 22, 2017 at 1:27 AM, Jason A. Donenfeld <Jason@xxxxxxxxx> wrote: > On older versions of binutils, \sym points to an aligned address. On > newer versions of binutils, \sym sometimes points to the unaligned thumb > address in mysterious and buggy circumstances. In order to homogenize > this behavior, rather than adding 1, we simply OR in 1, so that already > unaligned instructions don't change. This fix is required for a > pedestrian THUMB2_KERNEL to boot without crashing when built with > non-old binutils. > > While it works, the downside is that we have to add an `orr` instruction > to a fast path. The assembler can't do this at assemble time via "|1" > because "invalid operands (.text and *ABS* sections) for `|'", so we're > forced to do this. A better solution would be to have consistent > binutils behavior, or to have some kind of \sym feature detection that > won't turn into a maze of version comparisons. However, it's at the > moment unclear how to achieve this. > > The rest of this commit message contains all of the relevant > information. > > My tests concerned these versions: > broken: GNU ld (Gentoo 2.29.1 p3) 2.29.1 > working: GNU ld (GNU Binutils for Ubuntu) 2.26.1 > > These produced the following code: > --- broken 2017-11-21 17:44:14.523416082 +0100 > +++ working 2017-11-21 17:44:44.548461234 +0100 > @@ -133,7 +133,7 @@ > 160: f01a 0ff0 tst.w sl, #240 ; 0xf0 > 164: d111 bne.n 18a <__sys_trace> > 166: f5b7 7fc8 cmp.w r7, #400 ; 0x190 > - 16a: f2af 1e6a subw lr, pc, #362 ; 0x16a > + 16a: f2af 1e6b subw lr, pc, #363 ; 0x16b > 16e: bf38 it cc > 170: f858 f027 ldrcc.w pc, [r8, r7, lsl #2] > 174: a902 add r1, sp, #8 > > The differing instruction corresponds with this actual line in > arch/arm/kernel/entry-common.S: > badr lr, ret_fast_syscall @ return address > > Running the broken kernel results in a runtime OOPS with: > PC is at ret_fast_syscall+0x4/0x52 > LR is at ret_fast_syscall+0x2/0x52 > > The disassembly of that function for the crashing kernel is: > .text:00000000 ret_fast_syscall ; CODE XREF: sys_syscall+1C↓j > .text:00000000 CPSID I ; jumptable 00000840 cases 15,18-376 > .text:00000002 > .text:00000002 loc_2 ; DATA XREF: sys_syscall-6BA↓o > .text:00000002 LDR.W R2, [R9,#8] > .text:00000006 CMP.W R2, #0xBF000000 > > Signed-off-by: Jason A. Donenfeld <Jason@xxxxxxxxx> > Cc: stable@xxxxxxxxxxxxxxx FWIW, this patch fixes things for me. Never occurred to me that it was binutils that was at fault. Tested-by: Chen-Yu Tsai <wens@xxxxxxxx> with $ arm-linux-gnueabihf-ld -v GNU ld (GNU Binutils for Debian) 2.29.1 $ arm-linux-gnueabihf-gcc -v Using built-in specs. COLLECT_GCC=/usr/bin/arm-linux-gnueabihf-gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/arm-linux-gnueabihf/7/lto-wrapper Target: arm-linux-gnueabihf Configured with: ../src/configure -v --with-pkgversion='Debian 7.2.0-11' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-multiarch --disable-sjlj-exceptions --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --disable-werror --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=arm-linux-gnueabihf --program-prefix=arm-linux-gnueabihf- --includedir=/usr/arm-linux-gnueabihf/include Thread model: posix gcc version 7.2.0 (Debian 7.2.0-11) ChenYu