llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.92k stars 11.52k forks source link

Unwind information is not emitted for ThumbV7PILongThunks #46515

Open llvmbot opened 4 years ago

llvmbot commented 4 years ago
Bugzilla Link 47171
Version trunk
OS Linux
Reporter LLVM Bugzilla Contributor
CC @dwblaikie,@nico

Extended Description

The .debug_frame section of a .so for Android arm32 contains no FDEs covering ThumbV7PILongThunks. This is particularly problematic for Chromium where the .text section of libchrome.so is 80MB and contains 42k thunks, and a non-trivial amount of execution time is spent in the thunks.

This was observed in Chromium's clang built from 1bd7046e4ce0102adef6096a12a289d7f94b8c73.

It's not clear that a reduced repro is possible since thunks are only needed on arm32 when the text section is >32MB. To reproduce with Chromium:

  1. Follow https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md has instruction to set up a Chromium build for Android, but use the following file contents for the 'gn args out/Default' step:

target_os = "android" target_cpu = "arm" is_component_build = false

  1. After building chrome_public_apk the relevant .so is in out/Default/lib.unstripped/libchrome.so.

  2. Find the address of an example thunk: third_party/android_ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/bin/objdump -j .text -dC out/Default/lib.unstripped/libchrome.so | perl -lne 'print if /^.{8} <__ARMV7PILongThunk___cxa_finalize>/../^$/'

  3. Observe that no FDEs cover the address of the example thunk in the output of llvm-dwarfdump --debug-frame out/Debug/lib.unstripped/libchrome.so

llvmbot commented 4 years ago

Hmm, yes I assume the thunks must be generated by the linker. I observed the issue with gold. I don't have easy access to cross-linking builds of the other linkers to test with, unfortunately.

The suitable DWARF for these thunks would be same thing that gets produced by the compiler for e.g. virtual and non-virtual thunks, a CIE and (empty) FDE like this:

0000af08 0000000c ffffffff CIE Version: 3 Augmentation: "" Code alignment factor: 1 Data alignment factor: -4 Return address column: 14

DW_CFA_def_cfa: reg13 +0

0000afbc 0000000c 0000af08 FDE cie=0000af08 pc=011fa240...011fa246

Given that the linker is synthesizing code, it seems like it should support synthesizing unwind info too. :)

I tried to make a simple test case with assembly & nops but wasn't able to get the linker to generate a thunk in the case where functions were too far apart. I'm not sure the code it output was even valid for that matter. I'm guessing either the assembly-generated code is too different from what's produced by the compiler, or I'm not supplying the right linker flags, or both.

dwblaikie commented 4 years ago

These thunks are created by the linker, by the looks of it?

Generally the linker doesn't dabble in DWARF - doesn't create it/parse it/etc.

What do the various different linkers do with these? (bfd, gold, lld, ld64)

(but, all that said, I don't really know much about debug_frame - what would be suitable DWARF to produce for these thunks, etc)

You can probably make a simpler test case with assembly & nops to pad out the gaps to force thunks.

llvmbot commented 2 months ago

@llvm/issue-subscribers-backend-arm

Author: None (llvmbot)

| | | | --- | --- | | Bugzilla Link | [47171](https://llvm.org/bz47171) | | Version | trunk | | OS | Linux | | Reporter | LLVM Bugzilla Contributor | | CC | @dwblaikie,@nico | ## Extended Description The .debug_frame section of a .so for Android arm32 contains no FDEs covering ThumbV7PILongThunks. This is particularly problematic for Chromium where the .text section of libchrome.so is 80MB and contains 42k thunks, and a non-trivial amount of execution time is spent in the thunks. This was observed in Chromium's clang built from 1bd7046e4ce0102adef6096a12a289d7f94b8c73. It's not clear that a reduced repro is possible since thunks are only needed on arm32 when the text section is >32MB. To reproduce with Chromium: 1. Follow https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md has instruction to set up a Chromium build for Android, but use the following file contents for the 'gn args out/Default' step: target_os = "android" target_cpu = "arm" is_component_build = false 2. After building chrome_public_apk the relevant .so is in out/Default/lib.unstripped/libchrome.so. 3. Find the address of an example thunk: third_party/android_ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/bin/objdump -j .text -dC out/Default/lib.unstripped/libchrome.so | perl -lne 'print if /^.{8} <__ARMV7PILongThunk___cxa_finalize>/../^$/' 4. Observe that no FDEs cover the address of the example thunk in the output of llvm-dwarfdump --debug-frame out/Debug/lib.unstripped/libchrome.so
llvmbot commented 2 months ago

@llvm/issue-subscribers-debuginfo

Author: None (llvmbot)

| | | | --- | --- | | Bugzilla Link | [47171](https://llvm.org/bz47171) | | Version | trunk | | OS | Linux | | Reporter | LLVM Bugzilla Contributor | | CC | @dwblaikie,@nico | ## Extended Description The .debug_frame section of a .so for Android arm32 contains no FDEs covering ThumbV7PILongThunks. This is particularly problematic for Chromium where the .text section of libchrome.so is 80MB and contains 42k thunks, and a non-trivial amount of execution time is spent in the thunks. This was observed in Chromium's clang built from 1bd7046e4ce0102adef6096a12a289d7f94b8c73. It's not clear that a reduced repro is possible since thunks are only needed on arm32 when the text section is >32MB. To reproduce with Chromium: 1. Follow https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md has instruction to set up a Chromium build for Android, but use the following file contents for the 'gn args out/Default' step: target_os = "android" target_cpu = "arm" is_component_build = false 2. After building chrome_public_apk the relevant .so is in out/Default/lib.unstripped/libchrome.so. 3. Find the address of an example thunk: third_party/android_ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/bin/objdump -j .text -dC out/Default/lib.unstripped/libchrome.so | perl -lne 'print if /^.{8} <__ARMV7PILongThunk___cxa_finalize>/../^$/' 4. Observe that no FDEs cover the address of the example thunk in the output of llvm-dwarfdump --debug-frame out/Debug/lib.unstripped/libchrome.so