1 // Copyright 2021 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_PROFILER_CHROME_UNWIND_INFO_ANDROID_H_ 6 #define BASE_PROFILER_CHROME_UNWIND_INFO_ANDROID_H_ 7 8 #include <stdint.h> 9 10 #include "base/base_export.h" 11 #include "base/containers/span.h" 12 13 namespace base { 14 15 // Represents each entry in the function table (i.e. the second level of the 16 // function address table). 17 struct FunctionTableEntry { 18 // The offset into the 128kb page containing this function. Indexed by bits 19 // 1-16 of the pc offset from the start of the text section. 20 uint16_t function_start_address_page_instruction_offset; 21 22 // The byte index of the first offset for the function in the function 23 // offset table. 24 uint16_t function_offset_table_byte_index; 25 }; 26 27 // The header at the start of the unwind info resource, with offsets/sizes for 28 // the tables contained within the resource. 29 // 30 // The unwind info provides 4 tables which can translate an instruction address 31 // to a set of unwind instructions to unwind the function frame the instruction 32 // belongs to. 33 // 34 // `page_table` and `function_table` together locates which function the 35 // instruction address belongs to given an instruction address. 36 // 37 // `function_offset_table` and `unwind_instruction_table` together locates 38 // which sets of unwind instructions to execute given the function info 39 // obtained from `page_table` and `function_table`, and the offset between the 40 // instruction address and function start address. 41 // 42 // Design Doc: 43 // https://docs.google.com/document/d/1IYTmGCJZoiQ242xPUZX1fATD6ivsjU1TAt_fPv74ocs/edit?usp=sharing 44 struct BASE_EXPORT ChromeUnwindInfoHeaderAndroid { 45 // The offset in bytes from the start of the unwind info resource to the 46 // page table (i.e. the first level of the function address table). The page 47 // table represents discrete 128kb 'pages' of memory in the text section, 48 // each of which contains functions. The page table is indexed by bits 17 49 // and greater of the pc offset from the start of the text section. 50 // Indexing into page_table produces an index of function_table. 51 uint32_t page_table_byte_offset; 52 uint32_t page_table_entries; 53 54 // The offset in bytes from the start of the unwind info resource to the 55 // function table (i.e. the second level of the function address table). The 56 // function table represents the individual functions within a 128kb page. 57 // Each function is represented as a `FunctionTableEntry`. The relevant entry 58 // for a pc offset from the start of the text section is the one with the 59 // largest function_start_address_page_instruction_offset <= (pc_offset >> 1) 60 // & 0xffff. 61 uint32_t function_table_byte_offset; 62 uint32_t function_table_entries; 63 64 // The offset in bytes from the start of the unwind info resource to the 65 // function offset table. The function offset table represents the pc 66 // offsets from the start of each function along with indices into the 67 // unwind instructions for the offsets. The pc offsets and unwind indices 68 // are represented as (ULEB128, ULEB128) pairs in decreasing order of 69 // offset. Distinct sequences of (offset, index) pairs are concatenated in 70 // the table. 71 uint32_t function_offset_table_byte_offset; 72 uint32_t function_offset_table_size_in_bytes; 73 74 // The offset in bytes from the start of the unwind info resource to the 75 // unwind instruction table. The unwind instruction table represents 76 // distinct sequences of ARM compact unwind instructions[1] used across all 77 // functions in Chrome. The compact unwind instruction is a byte-oriented 78 // variable length encoding so is indexed by byte position. 79 // 1. See Exception handling ABI for the ARM architecture ABI, §9.3. 80 // https://developer.arm.com/documentation/ihi0038/b. 81 uint32_t unwind_instruction_table_byte_offset; 82 uint32_t unwind_instruction_table_size_in_bytes; 83 }; 84 85 struct BASE_EXPORT ChromeUnwindInfoAndroid { 86 ChromeUnwindInfoAndroid(span<const uint8_t> unwind_instruction_table, 87 span<const uint8_t> function_offset_table, 88 span<const FunctionTableEntry> function_table, 89 span<const uint32_t> page_table); 90 ~ChromeUnwindInfoAndroid(); 91 ChromeUnwindInfoAndroid(const ChromeUnwindInfoAndroid& other); 92 ChromeUnwindInfoAndroid& operator=(const ChromeUnwindInfoAndroid& other); 93 94 ChromeUnwindInfoAndroid(ChromeUnwindInfoAndroid&& other); 95 ChromeUnwindInfoAndroid& operator=(ChromeUnwindInfoAndroid&& other); 96 97 // Unwind instruction table is expected to have following memory layout: 98 // +-----------------------------+ 99 // | <--1 byte---> | 100 // +-----------------------------+ 101 // | pop {r4, r5, lr} | <- FUNC1 offset 10 102 // +-----------------------------+ 103 // | add sp, 16 | <- FUNC1 offset 4 104 // +-----------------------------+ 105 // | mov pc, lr | <- FUNC1 offset 0 (COMPLETE) 106 // +-----------------------------+ 107 // | pop {r4, r11} [byte 1/2] | <- FUNC2 offset 8 108 // +-----------------------------+ 109 // | pop {r4, r11} [byte 2/2] | 110 // +-----------------------------+ 111 // | ... | 112 // +-----------------------------+ 113 // Because we are unwinding the function, the next unwind instruction to 114 // execute always has smaller function offset. 115 // The function offsets are often discontinuous as not all instructions in 116 // the function have corresponding unwind instructions. 117 // 118 // See Exception handling ABI for the ARM architecture ABI, §9.3. 119 // https://developer.arm.com/documentation/ihi0038/b. 120 // for details in unwind instruction encoding. 121 // Only following instruction encodings are handled: 122 // - 00xxxxxx 123 // - 01xxxxxx 124 // - 1000iiii iiiiiiii 125 // - 1001nnnn 126 // - 10100nnn 127 // - 10101nnn 128 // - 10110000 129 // - 10110010 uleb128 130 span<const uint8_t> unwind_instruction_table; 131 132 // Function offset table is expected to have following memory layout: 133 // +---------------------+---------------------+ 134 // | <-----ULEB128-----> | <-----ULEB128-----> | 135 // +---------------------+---------------------+ 136 // | Offset | Unwind Index | 137 // +---------------------+---------------------+----- 138 // | 8 | XXX | | 139 // +---------------------+---------------------+ | 140 // | 3 | YYY |Function 1 141 // +---------------------+---------------------+ | 142 // | 0 | ZZZ | | 143 // +---------------------+---------------------+----- 144 // | 5 | AAA | | 145 // +---------------------+---------------------+Function 2 146 // | 0 | BBB | | 147 // +---------------------+---------------------+----- 148 // | ... | .... | 149 // +---------------------+---------------------+ 150 // The function offset table contains [offset, unwind index] pairs, where 151 // - offset: offset from function start address of an instruction that affects 152 // the unwind state, measured in two-byte instructions. 153 // - unwind index: unwind instruction location in unwind instruction table. 154 // 155 // Note: 156 // - Each function always ends at 0 offset, which corresponds to a terminal 157 // instruction in unwind instruction table. 158 // - Within each function section, offset strictly decreases. By doing so, 159 // each function's own terminal instruction will serve as termination 160 // condition when searching in the table. 161 span<const uint8_t> function_offset_table; 162 163 // The function table represents the individual functions within a 128kb page. 164 // The relevant entry for an instruction offset from the start of the text 165 // section is the one with the largest function_start_address_page_offset <= 166 // instruction_byte_offset_from_text_section_start. 167 // 168 // Function table is expected to have following memory layout: 169 // +--------------------+--------------------+ 170 // | <-----2 byte-----> | <-----2 byte-----> | 171 // +--------------------+--------------------+ 172 // | Page Offset | Offset Table Index | 173 // +--------------------+--------------------+----- 174 // | 10 | XXX | | 175 // +--------------------+--------------------+ | 176 // | ... | ... |Page 0x100 177 // +--------------------+--------------------+ | 178 // | 65500 | ZZZ | | 179 // +--------------------+--------------------+----- 180 // | 200 | AAA | | 181 // +--------------------+--------------------+ | 182 // | ... | ... |Page 0x101 183 // +--------------------+--------------------+ | 184 // | 65535 | BBB | | 185 // +--------------------+--------------------+----- 186 // 187 // Note: 188 // - Within each page, `Page Offset` strictly increases. 189 // - Each `FunctionTableEntry` represents a function where the start 190 // address falls into the page memory address range. 191 span<const FunctionTableEntry> function_table; 192 193 // The page table represents discrete 128kb 'pages' of memory in the text 194 // section, each of which contains functions. The page table is indexed by 195 // bits 17 and greater of the pc offset from the start of the text section. 196 // Indexing into page_table produces an index of function_table. 197 // 198 // The page table is expected to have following memory layout: 199 // +----------------+ 200 // | <-- 4 byte --> | 201 // +----------------+ 202 // | 0 | 203 // +----------------+ 204 // | 18 | 205 // +----------------+ 206 // | 18 | 207 // +----------------+ 208 // | 80 | 209 // +----------------+ 210 // | ... | 211 // +----------------+ 212 // Note: 213 // - The page start instructions in page table non-strictly increases, i.e 214 // empty page is allowed. 215 span<const uint32_t> page_table; 216 }; 217 218 // Creates `ChromeUnwindInfoAndroid` struct based on binary `data` assuming 219 // `data` starts with `ChromeUnwindInfoHeaderAndroid`. 220 BASE_EXPORT ChromeUnwindInfoAndroid 221 CreateChromeUnwindInfoAndroid(span<const uint8_t> data); 222 223 } // namespace base 224 225 #endif // BASE_PROFILER_CHROME_UNWIND_INFO_ANDROID_H_