Use verify when speed-profile gets an empty profile

Change the compiler filter to verify if we need to compile
speed-profile but we don't get a profile, or the profile is empty.
This will improve the clarity and the precision of the telemetry
data which usually expects speed-profile to outperform verify.

Test: gtest
Bug: 188655918
Change-Id: I215552e0001d56df0e0d676721f0a741ef2573be
4 files changed
tree: 27631b722b16cc7a71de86e847fe023ccf01a384
  1. adbconnection/
  2. artd/
  3. benchmark/
  4. build/
  5. cmdline/
  6. compiler/
  7. dalvikvm/
  8. dex2oat/
  9. dexdump/
  10. dexlayout/
  11. dexlist/
  12. dexoptanalyzer/
  13. disassembler/
  14. dt_fd_forward/
  15. imgdiag/
  16. libartbase/
  17. libartpalette/
  18. libartservice/
  19. libarttools/
  20. libdexfile/
  21. libelffile/
  22. libnativebridge/
  23. libnativeloader/
  24. libprofile/
  25. oatdump/
  26. odrefresh/
  27. openjdkjvm/
  28. openjdkjvmti/
  29. perfetto_hprof/
  30. profman/
  31. runtime/
  32. sigchainlib/
  33. simulator/
  34. test/
  35. tools/
  36. .clang-format
  37. .gitignore
  38. Android.bp
  39. Android.mk
  40. CleanSpec.mk
  41. CPPLINT.cfg
  42. METADATA
  43. MODULE_LICENSE_APACHE2
  44. NOTICE
  45. OWNERS
  46. PREUPLOAD.cfg
  47. README.md
  48. test.py
  49. TEST_MAPPING
README.md

Debugging

Stack Protectors

In the Android operating system all non-native system and application processes are forked from the Zygote. As such, one of the Zygote's responsibilities is to change the stack protector cookie when a new process is created in order to prevent all processes from sharing the same value. When the stack protector cookie is changed all existing stack frames that have protectors will fail their check. This means that the call path from ZygoteInit.main() to the fork site in zygote::ForkCommon() cannot contain any functions with stack protectors. This must be true not just for the main zygotes, but also for the AppZygotes and WebViewZygote.

To achieve this goal the relevant native Zygote functions in frameworks/base and several functions in the ART interpreter have bee marked with __attribute__((no_stack_protector)). If you are debugging an issue with a SIGABRT message of "stack corruption detected" and you are sure it isn't a legitimate case of corruption it is possible that a function has been added somewhere along this critical path and contains a stack protector.

If the function in the stack immediately proceeding the call to __stack_chk_fail corresponds to a recently added call site in a function already marked with NO_STACK_PROTECTOR it is probably sufficient to add this annotation macro to the offending function. However, it is possible for a properly annotated function to still contain a stack protector. This can be caused when a function marked as alwaysinline, but not no_stack_protector, is called. Because the compiler views undefined and a negative condition as the same thing it can't tell the difference between "no annotation" and no_stack_protector. Thus it will promote the stack protector status of the caller, causing this hard to detect behavior.

The first thing to check is to see if any uses of the raw __attribute__((alwaysinline)) have been added. If this has occurred, replace the raw attribute with the ALWAYS_INLINE macro when possible or, if not, add the no_stack_protector to the attribute list. If this doesn't solve the issue (this should be very rare), you will need to use the following steps to get a list of the inline events in the function that are caused by alwaysinline.

Debugging alwaysinline

First, you will need to obtain a copy of the LLVM opt binary built in debug mode. You can do this by downloading and building a version from source, using a copy from Google3, or asking a member of the LLVM team to provide one.

Next, successfully build a copy of android and then run the following command:

$> prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-${TARGET_PRODUCT}.ninja -t query path/to/file.cc

This will produce a list of object files generated by the build system from this source file. Select one of those object files and use it in this command:

$> prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-${TARGET_PRODUCT}.ninja -t commands path/to/object/file.o | tail -1

Now you can add the -save-temps option to the command you got from the previous command and run it in your Android root directory. This will produce a series of <file_basename>.* files. Next, run

$> llvm-dis <file_basename>.bc

to convert the .bc file to a .ll file. The next step is to run the .ll file through opt and get it to list the inline events triggered by alwaysinline.

$> opt <file_basename>.ll -passes=inline -filter-print-funcs=<mangled function name> -S 2>&1 1>/dev/null -debug-only=inline -o /dev/null | grep always > <file_basename>_inlines.txt

This file contains a bunch of extraneous information which can be removed via this command:

$> cut -d @ -f 2 < <file_basename>_inlines.txt | cut -d \( -f 1 > <file_basename>_inlines_names_only.txt

Next you will need to open the <file_basename>.ll file in a text editor and locate the beginning and ending line numbers for the function in question. Use those lines in the command below for the $1 and $2 values.

sed -n '$1,$2p' <file_basename>.ll > <function_name>.ll

Lastly, you can get the set of functions inlined into your target function via alwaysinline using this command:

for i in `cat <file_basename>_inlines_names_only.txt`; do grep $i <function_name>.ll; done