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