Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame^] | 1 | // Copyright 2021 The Chromium Authors |
Charlie Hu | d5c1403 | 2021-08-26 21:45:59 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Charlie Hu | e0a13a7 | 2021-09-24 21:57:39 | [diff] [blame] | 5 | #ifndef BASE_PROFILER_CHROME_UNWINDER_ANDROID_V2_H_ |
| 6 | #define BASE_PROFILER_CHROME_UNWINDER_ANDROID_V2_H_ |
Charlie Hu | d5c1403 | 2021-08-26 21:45:59 | [diff] [blame] | 7 | |
| 8 | #include <stdint.h> |
| 9 | |
| 10 | #include "base/base_export.h" |
Charlie Hu | 235c6b7 | 2021-09-13 20:50:01 | [diff] [blame] | 11 | #include "base/containers/span.h" |
Charlie Hu | 78e0040 | 2021-10-13 06:10:43 | [diff] [blame] | 12 | #include "base/profiler/chrome_unwind_info_android.h" |
| 13 | #include "base/profiler/module_cache.h" |
Charlie Hu | d5c1403 | 2021-08-26 21:45:59 | [diff] [blame] | 14 | #include "base/profiler/register_context.h" |
Charlie Hu | 78e0040 | 2021-10-13 06:10:43 | [diff] [blame] | 15 | #include "base/profiler/unwinder.h" |
Charlie Hu | 235c6b7 | 2021-09-13 20:50:01 | [diff] [blame] | 16 | #include "third_party/abseil-cpp/absl/types/optional.h" |
Charlie Hu | d5c1403 | 2021-08-26 21:45:59 | [diff] [blame] | 17 | |
| 18 | namespace base { |
| 19 | |
Charlie Hu | 78e0040 | 2021-10-13 06:10:43 | [diff] [blame] | 20 | // Chrome unwinder implementation for Android, using ChromeUnwindInfoAndroid, |
| 21 | // a separate binary resource. This implementation is intended to replace |
| 22 | // `ChromeUnwinderAndroid`, which uses ArmCfiTable. |
| 23 | class BASE_EXPORT ChromeUnwinderAndroidV2 : public Unwinder { |
| 24 | public: |
| 25 | ChromeUnwinderAndroidV2(const ChromeUnwindInfoAndroid& unwind_info, |
| 26 | uintptr_t chrome_module_base_address, |
| 27 | uintptr_t text_section_start_address); |
| 28 | ChromeUnwinderAndroidV2(const ChromeUnwinderAndroidV2&) = delete; |
| 29 | ChromeUnwinderAndroidV2& operator=(const ChromeUnwinderAndroidV2&) = delete; |
| 30 | |
| 31 | // Unwinder: |
| 32 | bool CanUnwindFrom(const Frame& current_frame) const override; |
| 33 | UnwindResult TryUnwind(RegisterContext* thread_context, |
| 34 | uintptr_t stack_top, |
| 35 | std::vector<Frame>* stack) const override; |
| 36 | |
| 37 | private: |
| 38 | const ChromeUnwindInfoAndroid unwind_info_; |
| 39 | const uintptr_t chrome_module_base_address_; |
| 40 | const uintptr_t text_section_start_address_; |
| 41 | }; |
| 42 | |
| 43 | // Following functions are exposed for testing purpose only. |
Charlie Hu | 027f8a1 | 2021-09-23 23:25:19 | [diff] [blame] | 44 | struct FunctionTableEntry; |
| 45 | |
Charlie Hu | 82c2ed35 | 2021-09-14 17:58:55 | [diff] [blame] | 46 | enum class UnwindInstructionResult { |
| 47 | kCompleted, // Signals the end of unwind process. |
| 48 | kInstructionPending, // Continues to unwind next instruction. |
| 49 | kAborted, // Unable to unwind. |
Charlie Hu | d5c1403 | 2021-08-26 21:45:59 | [diff] [blame] | 50 | }; |
| 51 | |
Charlie Hu | 027f8a1 | 2021-09-23 23:25:19 | [diff] [blame] | 52 | // Execute a single unwind instruction on the given thread_context, and moves |
| 53 | // `instruction` to point to next instruction right after the executed |
| 54 | // instruction. |
Charlie Hu | 01b7e66 | 2021-09-13 14:51:36 | [diff] [blame] | 55 | // |
| 56 | // Arguments: |
| 57 | // instruction: The pointer to the instruction to execute. This pointer will |
| 58 | // be advanced by the size of the instruction executed after the |
| 59 | // function call. |
| 60 | // pc_was_updated: Set to true if the pc was updated by the instruction |
| 61 | // execution. Used to decide whether to copy lr to pc on |
| 62 | // COMPLETE. |
| 63 | // thread_context: The thread_context the instruction operates on. |
Charlie Hu | d5c1403 | 2021-08-26 21:45:59 | [diff] [blame] | 64 | BASE_EXPORT UnwindInstructionResult |
| 65 | ExecuteUnwindInstruction(const uint8_t*& instruction, |
Charlie Hu | 01b7e66 | 2021-09-13 14:51:36 | [diff] [blame] | 66 | bool& pc_was_updated, |
Charlie Hu | d5c1403 | 2021-08-26 21:45:59 | [diff] [blame] | 67 | RegisterContext* thread_context); |
Charlie Hu | f36b2f6 | 2021-09-01 22:31:20 | [diff] [blame] | 68 | |
Charlie Hu | 235c6b7 | 2021-09-13 20:50:01 | [diff] [blame] | 69 | // Represents an index that can locate a specific entry on function offset |
| 70 | // table. |
| 71 | struct FunctionOffsetTableIndex { |
| 72 | // Number of 2-byte instructions between the instruction of interest and |
Charlie Hu | 78e0040 | 2021-10-13 06:10:43 | [diff] [blame] | 73 | // function start address. |
Charlie Hu | 235c6b7 | 2021-09-13 20:50:01 | [diff] [blame] | 74 | int instruction_offset_from_function_start; |
| 75 | // The byte index of the first offset for the function in the function |
| 76 | // offset table. |
| 77 | uint16_t function_offset_table_byte_index; |
| 78 | }; |
| 79 | |
Charlie Hu | 78e0040 | 2021-10-13 06:10:43 | [diff] [blame] | 80 | // Given function offset table entry, finds the first unwind instruction to |
| 81 | // execute in unwind instruction table. |
Charlie Hu | f36b2f6 | 2021-09-01 22:31:20 | [diff] [blame] | 82 | // |
Charlie Hu | f36b2f6 | 2021-09-01 22:31:20 | [diff] [blame] | 83 | // Arguments: |
Charlie Hu | 78e0040 | 2021-10-13 06:10:43 | [diff] [blame] | 84 | // function_offset_table_entry: An entry in function offset table. See |
Charlie Hu | 027f8a1 | 2021-09-23 23:25:19 | [diff] [blame] | 85 | // `ChromeUnwindInfoAndroid::function_offset_table` for details. |
Charlie Hu | 78e0040 | 2021-10-13 06:10:43 | [diff] [blame] | 86 | // instruction_offset_from_function_start: Number of 2-byte instructions |
| 87 | // between the instruction of interest and function start address. |
| 88 | // |
| 89 | // Returns: |
| 90 | // The index of the first unwind instruction to execute in |
| 91 | // `ChromeUnwindInfoAndroid::unwind_instruction_table`. |
| 92 | BASE_EXPORT uintptr_t |
| 93 | GetFirstUnwindInstructionIndexFromFunctionOffsetTableEntry( |
| 94 | const uint8_t* function_offset_table_entry, |
| 95 | int instruction_offset_from_function_start); |
Charlie Hu | 235c6b7 | 2021-09-13 20:50:01 | [diff] [blame] | 96 | |
Charlie Hu | d302851 | 2021-10-13 18:34:21 | [diff] [blame] | 97 | // Given an instruction_byte_offset_from_text_section_start, finds the |
| 98 | // corresponding `FunctionOffsetTableIndex`. |
Charlie Hu | 235c6b7 | 2021-09-13 20:50:01 | [diff] [blame] | 99 | // |
Charlie Hu | 027f8a1 | 2021-09-23 23:25:19 | [diff] [blame] | 100 | // Arguments: |
| 101 | // page_start_instructions: A list of page_numbers. See |
| 102 | // `ChromeUnwindInfoAndroid::page_table` for details. |
| 103 | // function_offsets_table_indices: A list of `FunctionTableEntry`. See |
| 104 | // `ChromeUnwindInfoAndroid::function_table` for details. |
Charlie Hu | d302851 | 2021-10-13 18:34:21 | [diff] [blame] | 105 | // instruction_byte_offset_from_text_section_start: The distance in bytes |
| 106 | // between the instruction of interest and text section start. |
Charlie Hu | 235c6b7 | 2021-09-13 20:50:01 | [diff] [blame] | 107 | BASE_EXPORT const absl::optional<FunctionOffsetTableIndex> |
| 108 | GetFunctionTableIndexFromInstructionOffset( |
| 109 | span<const uint32_t> page_start_instructions, |
| 110 | span<const FunctionTableEntry> function_offset_table_indices, |
Charlie Hu | d302851 | 2021-10-13 18:34:21 | [diff] [blame] | 111 | uint32_t instruction_byte_offset_from_text_section_start); |
Charlie Hu | 235c6b7 | 2021-09-13 20:50:01 | [diff] [blame] | 112 | |
Charlie Hu | d5c1403 | 2021-08-26 21:45:59 | [diff] [blame] | 113 | } // namespace base |
| 114 | |
Charlie Hu | e0a13a7 | 2021-09-24 21:57:39 | [diff] [blame] | 115 | #endif // BASE_PROFILER_CHROME_UNWINDER_ANDROID_V2_H_ |