• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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