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