Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Relocation R_ARM_THM_JUMP24 error when linking stage 2 MallocChecker.cpp on ARMv7 #27812

Open Quuxplusone opened 8 years ago

Quuxplusone commented 8 years ago
Bugzilla Link PR27813
Status NEW
Importance P normal
Reported by Renato Golin (rengolin@gmail.com)
Reported on 2016-05-19 04:44:49 -0700
Last modified on 2016-09-14 04:49:39 -0700
Version trunk
Hardware PC Linux
CC diana.picus@linaro.org, llvm-bugs@lists.llvm.org, smithp352@googlemail.com, t.p.northover@gmail.com
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
This error shown up on
http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-a15-full-sh/builds/3526:

lib/libclangStaticAnalyzerCheckers.a(MallocChecker.cpp.o): In function
`clang::ento::ProgramStatePartialTrait<llvm::ImmutableMap<clang::ento::SymExpr
const*, (anonymous namespace)::ReallocPair,
llvm::ImutKeyValueInfo<clang::ento::SymExpr const*, (anonymous
namespace)::ReallocPair> > >::DeleteContext(void*)':

/home/linaro/devel/buildbot/clang-cmake-thumbv7-a15-full-sh/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp:(.text._ZN5clang4ento24ProgramStatePartialTraitIN4llvm12ImmutableMapIPKNS0_7SymExprEN12_GLOBAL__N_111ReallocPairENS2_16ImutKeyValueInfoIS6_S8_EEEEE13DeleteContextEPv+0x88):

relocation truncated to fit: R_ARM_THM_JUMP24 against symbol `operator
delete(void*)@@GLIBCXX_3.4' defined in .text section in /usr/lib/gcc/arm-linux-
gnueabihf/4.8/libstdc++.so

And subsequently disappeared from
http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-a15-full-sh/builds/3527.

I have done a bisect on a similar machine overnight using the exact same
configuration (Chromebook, kernel 3.8.11, Ubuntu Trusty, GCC 4.8.2-19ubuntu1,
ld BFD 2.24) and got nothing.

Looks like a heisenbug... :(
Quuxplusone commented 8 years ago
My interpretation of the of the error message is that the relocation is from an
MallocChecker.o to operator delete(void*) defined in libstdc++.so

I'm a bit confused by this error message as I would have expected the
R_ARM_THM_JUMP24 to be resolved against the PLT, or to a state change veneer
(thunk) prior to calling the PLT entry for operator delete(void*).

It is possible that the error message is reporting the final destination
symbol, skipping over the PLT et al. I'm not familiar with the ld internals
whether this is the case.

Speculating wildly: the only suspicious command line option is -fvisibility-
inlines-hidden . Could it be possible that a local inline operator
delete(void*) with hidden visibility is generated which is somehow clashing
with the operator delete(void*) in libstdc++.so.
Quuxplusone commented 8 years ago
Happening again on clang-cmake-armv7-a15:

DebugHandlerBase.cpp:(.text._ZN4llvm8DenseMapIPKNS_12MachineInstrEPNS_8MCSymbolENS_12DenseMapInfoIS3_EENS_6detail12DenseMapPairIS3_S5_EEE4growEj[_ZN4llvm8DenseMapIPKNS_12MachineInstrEPNS_8MCSymbolENS_12DenseMapInfoIS3_EENS_6detail12DenseMapPairIS3_S5_EEE4growEj]+0x18a):
relocation truncated to fit: R_ARM_THM_JUMP24 against symbol `operator
delete(void*)@@GLIBCXX_3.4' defined in .text section in /usr/lib/gcc/arm-linux-
gnueabihf/4.8/libstdc++.so
collect2: error: ld returned 1 exit status
Quuxplusone commented 8 years ago
I think I know what the problem is and I think it is an ld bug.

To reproduce we need a shared library and an assembler file:
-- shared.c --
int func(void) {
    return 0;
}
arm-linux-gnueabihf-gcc shared.c --shared -fPIC -o shared.so

-- space.s --
 .text
 .syntax unified
 .thumb
 .global sp
 .type sp,%function
 .space (1024 * 1024 * 16) - 0x108
 .space 2
 .global func2
 .type func2,%function
func2:
 b.w func

arm-linux-gnueabihf-gcc space.s -fPIC --shared  -O2 -o test.axf shared.so -
mthumb
(.text+0xfffefa): relocation truncated to fit: R_ARM_THM_JUMP24 against symbol
`func' defined in .text section in shared.so
collect2: error: ld returned 1 exit status

All plt entries are ARM state and b.w cannot be changed to a blx. The linker
must either insert a state change stub or insert an inline header in front of
the plt entry to change state (bx pc, nop). When in range ld will redirect b.w
to the plt entry header (Thumb entry point), when not in range a stub that
changes state and redirects to the ARM entry point.

My theory is that the problem exists when the b.w is exactly at maximum range
from the ARM plt entry, but not in range from the Thumb entry point. The code
to decide whether a stub is needed measures range to the ARM entry point,
thinks it is in range and doesn't generate a stub. Later the relocation
measures range to the thumb entry point and fails.
Quuxplusone commented 8 years ago

I've raised https://sourceware.org/bugzilla/show_bug.cgi?id=20608 on binutils for the ld problem.