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