summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--OWNERS4
-rw-r--r--adb/Android.bp374
-rw-r--r--adb/Android.mk387
-rw-r--r--adb/CPPLINT.cfg2
-rw-r--r--adb/adb.cpp88
-rw-r--r--adb/adb.h2
-rw-r--r--adb/adb_auth.h2
-rw-r--r--adb/client/adb_client.cpp (renamed from adb/adb_client.cpp)0
-rw-r--r--adb/client/adb_client.h (renamed from adb/adb_client.h)0
-rw-r--r--adb/client/auth.cpp (renamed from adb/adb_auth_host.cpp)27
-rw-r--r--adb/client/bugreport.cpp (renamed from adb/bugreport.cpp)0
-rw-r--r--adb/client/bugreport.h (renamed from adb/bugreport.h)0
-rw-r--r--adb/client/commandline.cpp (renamed from adb/commandline.cpp)0
-rw-r--r--adb/client/commandline.h (renamed from adb/commandline.h)0
-rw-r--r--adb/client/console.cpp (renamed from adb/console.cpp)0
-rw-r--r--adb/client/file_sync_client.cpp (renamed from adb/file_sync_client.cpp)0
-rw-r--r--adb/client/line_printer.cpp (renamed from adb/line_printer.cpp)0
-rw-r--r--adb/client/line_printer.h (renamed from adb/line_printer.h)0
-rw-r--r--adb/client/main.cpp18
-rw-r--r--adb/client/transport_mdns.cpp (renamed from adb/transport_mdns.cpp)0
-rw-r--r--adb/client/usb_libusb.cpp2
-rw-r--r--adb/daemon/auth.cpp (renamed from adb/adbd_auth.cpp)7
-rw-r--r--adb/daemon/file_sync_service.cpp (renamed from adb/file_sync_service.cpp)0
-rw-r--r--adb/daemon/framebuffer_service.cpp (renamed from adb/framebuffer_service.cpp)0
-rw-r--r--adb/daemon/jdwp_service.cpp (renamed from adb/jdwp_service.cpp)4
-rw-r--r--adb/daemon/main.cpp6
-rw-r--r--adb/daemon/remount_service.cpp (renamed from adb/remount_service.cpp)26
-rw-r--r--adb/daemon/set_verity_enable_state_service.cpp (renamed from adb/set_verity_enable_state_service.cpp)0
-rw-r--r--adb/daemon/shell_service.cpp (renamed from adb/shell_service.cpp)0
-rw-r--r--adb/daemon/shell_service_test.cpp (renamed from adb/shell_service_test.cpp)0
-rw-r--r--adb/fdevent.cpp44
-rw-r--r--adb/fdevent_test.cpp28
-rw-r--r--adb/protocol.txt6
-rw-r--r--adb/services.cpp1
-rw-r--r--adb/sockets.cpp25
-rw-r--r--adb/transport.cpp367
-rw-r--r--adb/transport.h80
-rw-r--r--adb/transport_local.cpp8
-rw-r--r--adb/transport_mdns_unsupported.cpp18
-rw-r--r--adb/transport_usb.cpp28
-rw-r--r--base/Android.bp50
-rw-r--r--base/include/android-base/strings.h4
-rw-r--r--base/logging.cpp2
-rw-r--r--base/properties.cpp5
-rw-r--r--bootstat/Android.bp3
-rw-r--r--debuggerd/Android.bp15
-rw-r--r--debuggerd/Android.mk1
-rw-r--r--debuggerd/debuggerd_test.cpp51
-rw-r--r--debuggerd/handler/debuggerd_fallback.cpp16
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/utility.h2
-rw-r--r--debuggerd/libdebuggerd/test/dump_memory_test.cpp46
-rw-r--r--debuggerd/libdebuggerd/tombstone.cpp22
-rw-r--r--debuggerd/libdebuggerd/utility.cpp10
-rw-r--r--debuggerd/seccomp_policy/crash_dump.arm.policy4
-rw-r--r--debuggerd/seccomp_policy/crash_dump.arm64.policy4
-rw-r--r--debuggerd/seccomp_policy/crash_dump.policy.def8
-rw-r--r--debuggerd/seccomp_policy/crash_dump.x86.policy4
-rw-r--r--debuggerd/seccomp_policy/crash_dump.x86_64.policy4
-rw-r--r--demangle/Android.bp4
-rw-r--r--diagnose_usb/Android.bp13
-rw-r--r--diagnose_usb/OWNERS2
-rw-r--r--diagnose_usb/diagnose_usb.cpp (renamed from adb/diagnose_usb.cpp)2
-rw-r--r--diagnose_usb/include/diagnose_usb.h (renamed from adb/diagnose_usb.h)0
-rw-r--r--fastboot/Android.mk4
-rw-r--r--fs_mgr/fs_mgr_fstab.cpp12
-rw-r--r--fs_mgr/fs_mgr_priv.h3
-rw-r--r--fs_mgr/include_fstab/fstab/fstab.h2
-rw-r--r--healthd/BatteryMonitor.cpp6
-rw-r--r--init/Android.bp67
-rw-r--r--init/README.md6
-rw-r--r--init/action.cpp236
-rw-r--r--init/action.h50
-rw-r--r--init/action_manager.cpp116
-rw-r--r--init/action_manager.h59
-rw-r--r--init/action_parser.cpp158
-rw-r--r--init/action_parser.h49
-rw-r--r--init/builtins.cpp8
-rw-r--r--init/capabilities.cpp11
-rw-r--r--init/capabilities.h11
-rw-r--r--init/host_init_parser.cpp82
-rw-r--r--init/host_init_stubs.cpp59
-rw-r--r--init/host_init_stubs.h60
-rw-r--r--init/init.cpp19
-rw-r--r--init/init.h5
-rw-r--r--init/init_test.cpp2
-rw-r--r--init/parser.cpp24
-rw-r--r--init/parser.h7
-rw-r--r--init/property_service.cpp160
-rw-r--r--init/property_service.h3
-rw-r--r--init/property_service_test.cpp6
-rw-r--r--init/reboot.cpp114
-rw-r--r--init/service.cpp26
-rw-r--r--init/subcontext.cpp26
-rw-r--r--init/subcontext.h1
-rw-r--r--init/test_service/Android.bp5
-rw-r--r--init/util.cpp33
-rw-r--r--init/util.h2
-rw-r--r--libappfuse/Android.bp4
-rw-r--r--libasyncio/Android.bp6
-rw-r--r--libbacktrace/Android.bp12
-rw-r--r--libbacktrace/Backtrace.cpp4
-rw-r--r--libbacktrace/BacktraceMap.cpp12
-rw-r--r--libbacktrace/UnwindStack.cpp25
-rw-r--r--libbacktrace/UnwindStackMap.cpp20
-rw-r--r--libbacktrace/UnwindStackMap.h4
-rw-r--r--libbacktrace/include/backtrace/Backtrace.h5
-rw-r--r--libbacktrace/include/backtrace/BacktraceMap.h14
-rw-r--r--libcutils/fs_config.cpp10
-rw-r--r--libcutils/include/cutils/trace.h3
-rw-r--r--libion/Android.bp1
-rw-r--r--libion/ion_test.c2
-rw-r--r--liblog/include/android/log.h30
-rw-r--r--liblog/liblog.map.txt4
-rw-r--r--libmemunreachable/Android.bp8
-rw-r--r--libmemunreachable/tests/Binder_test.cpp16
-rw-r--r--libnativebridge/Android.bp10
-rw-r--r--libnativeloader/test/Android.bp11
-rw-r--r--libpackagelistparser/Android.bp5
-rw-r--r--libprocessgroup/Android.bp2
-rw-r--r--libprocessgroup/processgroup.cpp244
-rw-r--r--libprocinfo/Android.bp11
-rw-r--r--libsystem/Android.bp2
-rw-r--r--libunwindstack/Android.bp11
-rw-r--r--libunwindstack/DexFiles.cpp8
-rw-r--r--libunwindstack/DwarfOp.cpp54
-rw-r--r--libunwindstack/DwarfOp.h386
-rw-r--r--libunwindstack/DwarfSection.cpp80
-rw-r--r--libunwindstack/Elf.cpp55
-rw-r--r--libunwindstack/ElfInterface.cpp71
-rw-r--r--libunwindstack/MapInfo.cpp14
-rw-r--r--libunwindstack/RegsArm.cpp13
-rw-r--r--libunwindstack/RegsArm64.cpp12
-rw-r--r--libunwindstack/RegsInfo.h66
-rw-r--r--libunwindstack/RegsMips.cpp14
-rw-r--r--libunwindstack/RegsMips64.cpp14
-rw-r--r--libunwindstack/RegsX86.cpp10
-rw-r--r--libunwindstack/RegsX86_64.cpp11
-rw-r--r--libunwindstack/Unwinder.cpp40
-rw-r--r--libunwindstack/include/unwindstack/DwarfSection.h6
-rw-r--r--libunwindstack/include/unwindstack/Elf.h6
-rw-r--r--libunwindstack/include/unwindstack/ElfInterface.h1
-rw-r--r--libunwindstack/include/unwindstack/Regs.h2
-rw-r--r--libunwindstack/include/unwindstack/RegsArm.h2
-rw-r--r--libunwindstack/include/unwindstack/RegsArm64.h2
-rw-r--r--libunwindstack/include/unwindstack/RegsMips.h2
-rw-r--r--libunwindstack/include/unwindstack/RegsMips64.h2
-rw-r--r--libunwindstack/include/unwindstack/RegsX86.h2
-rw-r--r--libunwindstack/include/unwindstack/RegsX86_64.h2
-rw-r--r--libunwindstack/include/unwindstack/Unwinder.h8
-rw-r--r--libunwindstack/tests/DexFilesTest.cpp42
-rw-r--r--libunwindstack/tests/DwarfOpTest.cpp457
-rw-r--r--libunwindstack/tests/DwarfSectionImplTest.cpp17
-rw-r--r--libunwindstack/tests/ElfCacheTest.cpp63
-rw-r--r--libunwindstack/tests/ElfInterfaceTest.cpp173
-rw-r--r--libunwindstack/tests/RegsFake.h4
-rw-r--r--libunwindstack/tests/RegsTest.cpp114
-rw-r--r--libunwindstack/tests/UnwindOfflineTest.cpp344
-rw-r--r--libunwindstack/tests/UnwinderTest.cpp61
-rw-r--r--libunwindstack/tools/unwind_info.cpp5
-rw-r--r--libunwindstack/tools/unwind_reg_info.cpp5
-rw-r--r--libunwindstack/tools/unwind_symbols.cpp5
-rw-r--r--libutils/Android.bp16
-rw-r--r--libutils/tests/Android.bp10
-rw-r--r--libvndksupport/Android.bp5
-rw-r--r--libvndksupport/tests/Android.bp7
-rw-r--r--libziparchive/zip_archive.cc2
-rw-r--r--lmkd/Android.bp9
-rw-r--r--lmkd/lmkd.c368
-rw-r--r--logcat/Android.bp7
-rw-r--r--logd/Android.bp2
-rw-r--r--logd/LogBuffer.cpp2
-rw-r--r--logwrapper/Android.bp2
-rw-r--r--rootdir/Android.mk22
-rw-r--r--rootdir/init.rc9
-rw-r--r--trusty/keymaster/Android.bp5
-rw-r--r--trusty/libtrusty/Android.bp5
-rw-r--r--trusty/libtrusty/tipc-test/Android.bp5
-rw-r--r--trusty/storage/lib/Android.bp2
-rw-r--r--trusty/storage/proxy/Android.bp2
-rw-r--r--usbd/Android.bp1
180 files changed, 3823 insertions, 2565 deletions
diff --git a/OWNERS b/OWNERS
index 682a067b3..1d319afb8 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1 +1,5 @@
1enh@google.com 1enh@google.com
2per-file libsysutils/src/Netlink* = ek@google.com
3per-file libsysutils/src/Netlink* = lorenzo@google.com
4per-file libsysutils/include/sysutils/Netlink* = ek@google.com
5per-file libsysutils/include/sysutils/Netlink* = lorenzo@google.com
diff --git a/adb/Android.bp b/adb/Android.bp
index 41f7b8952..ef425c177 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -12,40 +12,356 @@
12// See the License for the specific language governing permissions and 12// See the License for the specific language governing permissions and
13// limitations under the License. 13// limitations under the License.
14 14
15python_binary_host { 15cc_defaults {
16 name: "adb_integration_test_adb", 16 name: "adb_defaults",
17 main: "test_adb.py", 17
18 srcs: [ 18 cflags: [
19 "test_adb.py", 19 "-Wall",
20 ], 20 "-Wextra",
21 libs: [ 21 "-Werror",
22 "adb_py", 22 "-Wno-unused-parameter",
23 ], 23 "-Wno-missing-field-initializers",
24 version: { 24 "-Wvla",
25 py2: { 25 ],
26 enabled: true, 26 rtti: true,
27
28 clang_cflags: [
29 "-Wexit-time-destructors",
30 "-Wthread-safety",
31 ],
32
33 use_version_lib: true,
34
35 compile_multilib: "first",
36 product_variables: {
37 debuggable: {
38 cflags: [
39 "-DALLOW_ADBD_ROOT",
40 "-DALLOW_ADBD_DISABLE_VERITY",
41 "-DALLOW_ADBD_NO_AUTH",
42 ],
43 },
44 },
45
46 target: {
47 android: {
48 cflags: ["-DADB_HOST=0"],
49 },
50
51 host: {
52 cflags: ["-DADB_HOST=1"],
53 },
54
55 darwin: {
56 host_ldlibs: [
57 "-lpthread",
58 "-framework CoreFoundation",
59 "-framework IOKit",
60 "-lobjc",
61 ],
62 },
63
64 windows: {
65 cflags: [
66 // Define windows.h and tchar.h Unicode preprocessor symbols so that
67 // CreateFile(), _tfopen(), etc. map to versions that take wchar_t*, breaking the
68 // build if you accidentally pass char*. Fix by calling like:
69 // std::wstring path_wide;
70 // if (!android::base::UTF8ToWide(path_utf8, &path_wide)) { /* error handling */ }
71 // CreateFileW(path_wide.c_str());
72 "-DUNICODE=1",
73 "-D_UNICODE=1",
74
75 // -std=gnu++14 doesn't set _GNU_SOURCE on Windows.
76 "-D_GNU_SOURCE",
77 ],
78 },
79 },
80}
81
82// libadb
83// =========================================================
84// These files are compiled for both the host and the device.
85libadb_srcs = [
86 "adb.cpp",
87 "adb_io.cpp",
88 "adb_listeners.cpp",
89 "adb_trace.cpp",
90 "adb_utils.cpp",
91 "fdevent.cpp",
92 "services.cpp",
93 "sockets.cpp",
94 "socket_spec.cpp",
95 "sysdeps/errno.cpp",
96 "transport.cpp",
97 "transport_local.cpp",
98 "transport_usb.cpp",
99]
100
101libadb_posix_srcs = [
102 "sysdeps_unix.cpp",
103 "sysdeps/posix/network.cpp",
104]
105
106libadb_test_srcs = [
107 "adb_io_test.cpp",
108 "adb_listeners_test.cpp",
109 "adb_utils_test.cpp",
110 "fdevent_test.cpp",
111 "socket_spec_test.cpp",
112 "socket_test.cpp",
113 "sysdeps_test.cpp",
114 "sysdeps/stat_test.cpp",
115 "transport_test.cpp",
116]
117
118cc_library_host_static {
119 name: "libadb_host",
120 defaults: ["adb_defaults"],
121
122 srcs: libadb_srcs + [
123 "client/auth.cpp",
124 "client/usb_libusb.cpp",
125 "client/usb_dispatch.cpp",
126 "client/transport_mdns.cpp",
127 ],
128
129 target: {
130 linux: {
131 srcs: ["client/usb_linux.cpp"],
132 },
133 darwin: {
134 srcs: ["client/usb_osx.cpp"],
135 },
136
137 not_windows: {
138 srcs: libadb_posix_srcs,
139 },
140 windows: {
141 enabled: true,
142 srcs: [
143 "client/usb_windows.cpp",
144 "sysdeps_win32.cpp",
145 "sysdeps/win32/errno.cpp",
146 "sysdeps/win32/stat.cpp",
147 ],
148 shared_libs: ["AdbWinApi"],
149 },
150 },
151
152 static_libs: [
153 "libbase",
154 "libcrypto_utils",
155 "libcrypto",
156 "libdiagnose_usb",
157 "libmdnssd",
158 "libusb",
159 ],
160}
161
162cc_test_host {
163 name: "adb_test",
164 defaults: ["adb_defaults"],
165 srcs: libadb_test_srcs,
166 static_libs: [
167 "libadb_host",
168 "libbase",
169 "libcutils",
170 "libcrypto_utils",
171 "libcrypto",
172 "libmdnssd",
173 "libdiagnose_usb",
174 "libusb",
175 ],
176}
177
178cc_binary_host {
179 name: "adb",
180 tags: ["debug"],
181
182 defaults: ["adb_defaults"],
183
184 srcs: [
185 "client/adb_client.cpp",
186 "client/bugreport.cpp",
187 "client/commandline.cpp",
188 "client/file_sync_client.cpp",
189 "client/main.cpp",
190 "client/console.cpp",
191 "client/line_printer.cpp",
192 "shell_service_protocol.cpp",
193 ],
194
195 static_libs: [
196 "libadb_host",
197 "libbase",
198 "libcutils",
199 "libcrypto_utils",
200 "libcrypto",
201 "libdiagnose_usb",
202 "liblog",
203 "libmdnssd",
204 "libusb",
205 ],
206
207 stl: "libc++_static",
208
209 // Don't add anything here, we don't want additional shared dependencies
210 // on the host adb tool, and shared libraries that link against libc++
211 // will violate ODR
212 shared_libs: [],
213
214 target: {
215 darwin: {
216 cflags: [
217 "-Wno-sizeof-pointer-memaccess",
218 ],
219 },
220 windows: {
221 enabled: true,
222 ldflags: ["-municode"],
223 host_ldlibs: [
224 "-lws2_32",
225 "-lgdi32",
226 ],
227
228 shared_libs: ["AdbWinApi"],
229 required: [
230 "AdbWinUsbApi",
231 ],
232 },
27 }, 233 },
28 py3: { 234}
29 enabled: false, 235
236cc_library_static {
237 name: "libadbd",
238 defaults: ["adb_defaults"],
239
240 // libminadbd wants both, for some reason.
241 compile_multilib: "both",
242 srcs: libadb_srcs + libadb_posix_srcs + [
243 "daemon/auth.cpp",
244 "daemon/usb.cpp",
245 "daemon/jdwp_service.cpp",
246 ],
247
248 static_libs: [
249 "libasyncio",
250 "libbootloader_message",
251 "libcrypto_utils",
252 "libcrypto",
253 "libdiagnose_usb",
254 "libqemu_pipe",
255 "libbase",
256 ],
257}
258
259cc_binary {
260 name: "adbd",
261 defaults: ["adb_defaults"],
262
263 srcs: [
264 "daemon/main.cpp",
265 "daemon/mdns.cpp",
266 "daemon/file_sync_service.cpp",
267 "daemon/framebuffer_service.cpp",
268 "daemon/remount_service.cpp",
269 "daemon/set_verity_enable_state_service.cpp",
270 "daemon/shell_service.cpp",
271 "shell_service_protocol.cpp",
272 ],
273
274 cflags: [
275 "-D_GNU_SOURCE",
276 "-Wno-deprecated-declarations",
277 ],
278
279 strip: {
280 keep_symbols: true,
30 }, 281 },
31 }, 282
283 static_libs: [
284 "libadbd",
285 "libasyncio",
286 "libavb_user",
287 "libbootloader_message",
288 "libcrypto_utils",
289 "libcrypto",
290 "libdiagnose_usb",
291 "libfec",
292 "libfec_rs",
293 "libfs_mgr",
294 "liblog",
295 "libext4_utils",
296 "libmdnssd",
297 "libminijail",
298 "libselinux",
299 "libsquashfs_utils",
300 "libqemu_pipe",
301 "libdebuggerd_handler",
302
303 "libbase",
304 "libcutils",
305 ],
306}
307
308cc_test {
309 name: "adbd_test",
310 defaults: ["adb_defaults"],
311 srcs: libadb_test_srcs + [
312 "daemon/shell_service.cpp",
313 "daemon/shell_service_test.cpp",
314 "shell_service_protocol.cpp",
315 "shell_service_protocol_test.cpp",
316 ],
317
318 static_libs: [
319 "libadbd",
320 "libbase",
321 "libcutils",
322 "libcrypto_utils",
323 "libcrypto",
324 "libdiagnose_usb",
325 "liblog",
326 "libusb",
327 "libmdnssd",
328 ],
32} 329}
33 330
34python_binary_host { 331python_binary_host {
35 name: "adb_integration_test_device", 332 name: "adb_integration_test_adb",
36 main: "test_device.py", 333 main: "test_adb.py",
37 srcs: [ 334 srcs: [
38 "test_device.py", 335 "test_adb.py",
39 ], 336 ],
40 libs: [ 337 libs: [
41 "adb_py", 338 "adb_py",
42 ], 339 ],
43 version: { 340 version: {
44 py2: { 341 py2: {
45 enabled: true, 342 enabled: true,
343 },
344 py3: {
345 enabled: false,
346 },
46 }, 347 },
47 py3: { 348}
48 enabled: false, 349
350python_binary_host {
351 name: "adb_integration_test_device",
352 main: "test_device.py",
353 srcs: [
354 "test_device.py",
355 ],
356 libs: [
357 "adb_py",
358 ],
359 version: {
360 py2: {
361 enabled: true,
362 },
363 py3: {
364 enabled: false,
365 },
49 }, 366 },
50 },
51} 367}
diff --git a/adb/Android.mk b/adb/Android.mk
deleted file mode 100644
index e52f0cbef..000000000
--- a/adb/Android.mk
+++ /dev/null
@@ -1,387 +0,0 @@
1# Copyright 2005 The Android Open Source Project
2#
3# Android.mk for adb
4#
5
6LOCAL_PATH:= $(call my-dir)
7
8include $(LOCAL_PATH)/../platform_tools_tool_version.mk
9
10adb_host_sanitize :=
11adb_target_sanitize :=
12
13ADB_COMMON_CFLAGS := \
14 -frtti \
15 -Wall -Wextra -Werror \
16 -Wno-unused-parameter \
17 -Wno-missing-field-initializers \
18 -Wvla \
19 -DADB_VERSION="\"$(tool_version)\"" \
20
21ADB_COMMON_posix_CFLAGS := \
22 -Wexit-time-destructors \
23 -Wthread-safety \
24
25ADB_COMMON_linux_CFLAGS := \
26 $(ADB_COMMON_posix_CFLAGS) \
27
28ADB_COMMON_darwin_CFLAGS := \
29 $(ADB_COMMON_posix_CFLAGS) \
30
31# Define windows.h and tchar.h Unicode preprocessor symbols so that
32# CreateFile(), _tfopen(), etc. map to versions that take wchar_t*, breaking the
33# build if you accidentally pass char*. Fix by calling like:
34# std::wstring path_wide;
35# if (!android::base::UTF8ToWide(path_utf8, &path_wide)) { /* error handling */ }
36# CreateFileW(path_wide.c_str());
37ADB_COMMON_windows_CFLAGS := \
38 -DUNICODE=1 -D_UNICODE=1 \
39
40# libadb
41# =========================================================
42
43# Much of adb is duplicated in bootable/recovery/minadb and fastboot. Changes
44# made to adb rarely get ported to the other two, so the trees have diverged a
45# bit. We'd like to stop this because it is a maintenance nightmare, but the
46# divergence makes this difficult to do all at once. For now, we will start
47# small by moving common files into a static library. Hopefully some day we can
48# get enough of adb in here that we no longer need minadb. https://b/17626262
49LIBADB_SRC_FILES := \
50 adb.cpp \
51 adb_io.cpp \
52 adb_listeners.cpp \
53 adb_trace.cpp \
54 adb_utils.cpp \
55 fdevent.cpp \
56 sockets.cpp \
57 socket_spec.cpp \
58 sysdeps/errno.cpp \
59 transport.cpp \
60 transport_local.cpp \
61 transport_usb.cpp \
62
63LIBADB_TEST_SRCS := \
64 adb_io_test.cpp \
65 adb_listeners_test.cpp \
66 adb_utils_test.cpp \
67 fdevent_test.cpp \
68 socket_spec_test.cpp \
69 socket_test.cpp \
70 sysdeps_test.cpp \
71 sysdeps/stat_test.cpp \
72 transport_test.cpp \
73
74LIBADB_CFLAGS := \
75 $(ADB_COMMON_CFLAGS) \
76 -fvisibility=hidden \
77
78LIBADB_linux_CFLAGS := \
79 $(ADB_COMMON_linux_CFLAGS) \
80
81LIBADB_darwin_CFLAGS := \
82 $(ADB_COMMON_darwin_CFLAGS) \
83
84LIBADB_windows_CFLAGS := \
85 $(ADB_COMMON_windows_CFLAGS) \
86
87LIBADB_darwin_SRC_FILES := \
88 sysdeps_unix.cpp \
89 sysdeps/posix/network.cpp \
90 client/usb_dispatch.cpp \
91 client/usb_libusb.cpp \
92 client/usb_osx.cpp \
93
94LIBADB_linux_SRC_FILES := \
95 sysdeps_unix.cpp \
96 sysdeps/posix/network.cpp \
97 client/usb_dispatch.cpp \
98 client/usb_libusb.cpp \
99 client/usb_linux.cpp \
100
101LIBADB_windows_SRC_FILES := \
102 sysdeps_win32.cpp \
103 sysdeps/win32/errno.cpp \
104 sysdeps/win32/stat.cpp \
105 client/usb_dispatch.cpp \
106 client/usb_libusb.cpp \
107 client/usb_windows.cpp \
108
109LIBADB_TEST_windows_SRCS := \
110 sysdeps/win32/errno_test.cpp \
111 sysdeps_win32_test.cpp \
112
113include $(CLEAR_VARS)
114LOCAL_MODULE := libadbd_usb
115LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=0
116LOCAL_SRC_FILES := daemon/usb.cpp
117
118LOCAL_SANITIZE := $(adb_target_sanitize)
119
120# Even though we're building a static library (and thus there's no link step for
121# this to take effect), this adds the includes to our path.
122LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase libasyncio
123
124include $(BUILD_STATIC_LIBRARY)
125
126include $(CLEAR_VARS)
127LOCAL_MODULE := libadbd
128LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=0
129LOCAL_SRC_FILES := \
130 $(LIBADB_SRC_FILES) \
131 adbd_auth.cpp \
132 jdwp_service.cpp \
133 sysdeps/posix/network.cpp \
134
135LOCAL_SANITIZE := $(adb_target_sanitize)
136
137# Even though we're building a static library (and thus there's no link step for
138# this to take effect), this adds the includes to our path.
139LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libqemu_pipe libbase
140
141LOCAL_WHOLE_STATIC_LIBRARIES := libadbd_usb
142
143include $(BUILD_STATIC_LIBRARY)
144
145include $(CLEAR_VARS)
146LOCAL_MODULE := libadb
147LOCAL_MODULE_HOST_OS := darwin linux windows
148LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=1
149LOCAL_CFLAGS_windows := $(LIBADB_windows_CFLAGS)
150LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
151LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS)
152LOCAL_SRC_FILES := \
153 $(LIBADB_SRC_FILES) \
154 adb_auth_host.cpp \
155 transport_mdns.cpp \
156
157LOCAL_SRC_FILES_darwin := $(LIBADB_darwin_SRC_FILES)
158LOCAL_SRC_FILES_linux := $(LIBADB_linux_SRC_FILES)
159LOCAL_SRC_FILES_windows := $(LIBADB_windows_SRC_FILES)
160
161LOCAL_SANITIZE := $(adb_host_sanitize)
162
163# Even though we're building a static library (and thus there's no link step for
164# this to take effect), this adds the includes to our path.
165LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase libmdnssd libusb
166
167LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/
168LOCAL_MULTILIB := first
169
170include $(BUILD_HOST_STATIC_LIBRARY)
171
172include $(CLEAR_VARS)
173LOCAL_MODULE := adbd_test
174LOCAL_CFLAGS := -DADB_HOST=0 $(LIBADB_CFLAGS)
175LOCAL_SRC_FILES := \
176 $(LIBADB_TEST_SRCS) \
177 $(LIBADB_TEST_linux_SRCS) \
178 shell_service.cpp \
179 shell_service_protocol.cpp \
180 shell_service_protocol_test.cpp \
181 shell_service_test.cpp \
182
183LOCAL_SANITIZE := $(adb_target_sanitize)
184LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils libcrypto libusb libmdnssd
185LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
186include $(BUILD_NATIVE_TEST)
187
188# libdiagnose_usb
189# =========================================================
190
191include $(CLEAR_VARS)
192LOCAL_MODULE := libdiagnose_usb
193LOCAL_MODULE_HOST_OS := darwin linux windows
194LOCAL_CFLAGS := $(LIBADB_CFLAGS)
195LOCAL_SRC_FILES := diagnose_usb.cpp
196# Even though we're building a static library (and thus there's no link step for
197# this to take effect), this adds the includes to our path.
198LOCAL_STATIC_LIBRARIES := libbase
199include $(BUILD_HOST_STATIC_LIBRARY)
200
201# adb_test
202# =========================================================
203
204include $(CLEAR_VARS)
205LOCAL_MODULE := adb_test
206LOCAL_MODULE_HOST_OS := darwin linux windows
207LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
208LOCAL_CFLAGS_windows := $(LIBADB_windows_CFLAGS)
209LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
210LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS)
211LOCAL_SRC_FILES := \
212 $(LIBADB_TEST_SRCS) \
213 adb_client.cpp \
214 bugreport.cpp \
215 bugreport_test.cpp \
216 line_printer.cpp \
217 services.cpp \
218 shell_service_protocol.cpp \
219 shell_service_protocol_test.cpp \
220
221LOCAL_SRC_FILES_linux := $(LIBADB_TEST_linux_SRCS)
222LOCAL_SRC_FILES_darwin := $(LIBADB_TEST_darwin_SRCS)
223LOCAL_SRC_FILES_windows := $(LIBADB_TEST_windows_SRCS)
224LOCAL_SANITIZE := $(adb_host_sanitize)
225LOCAL_STATIC_LIBRARIES := \
226 libadb \
227 libbase \
228 libcrypto_utils \
229 libcrypto \
230 libcutils \
231 libdiagnose_usb \
232 libmdnssd \
233 libgmock_host \
234 libusb \
235
236# Set entrypoint to wmain from sysdeps_win32.cpp instead of main
237LOCAL_LDFLAGS_windows := -municode
238LOCAL_LDLIBS_linux := -lrt -ldl -lpthread
239LOCAL_LDLIBS_darwin := -framework CoreFoundation -framework IOKit -lobjc
240LOCAL_LDLIBS_windows := -lws2_32 -luserenv
241LOCAL_SHARED_LIBRARIES_windows := AdbWinApi
242
243LOCAL_MULTILIB := first
244
245include $(BUILD_HOST_NATIVE_TEST)
246
247# adb host tool
248# =========================================================
249include $(CLEAR_VARS)
250
251LOCAL_LDLIBS_linux := -lrt -ldl -lpthread
252
253LOCAL_LDLIBS_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon -lobjc
254
255# Use wmain instead of main
256LOCAL_LDFLAGS_windows := -municode
257LOCAL_LDLIBS_windows := -lws2_32 -lgdi32
258LOCAL_SHARED_LIBRARIES_windows := AdbWinApi
259LOCAL_REQUIRED_MODULES_windows := AdbWinUsbApi
260
261LOCAL_SRC_FILES := \
262 adb_client.cpp \
263 bugreport.cpp \
264 client/main.cpp \
265 console.cpp \
266 commandline.cpp \
267 file_sync_client.cpp \
268 line_printer.cpp \
269 services.cpp \
270 shell_service_protocol.cpp \
271
272LOCAL_CFLAGS += \
273 $(ADB_COMMON_CFLAGS) \
274 -D_GNU_SOURCE \
275 -DADB_HOST=1 \
276
277LOCAL_CFLAGS_windows := \
278 $(ADB_COMMON_windows_CFLAGS)
279
280LOCAL_CFLAGS_linux := \
281 $(ADB_COMMON_linux_CFLAGS) \
282
283LOCAL_CFLAGS_darwin := \
284 $(ADB_COMMON_darwin_CFLAGS) \
285 -Wno-sizeof-pointer-memaccess -Wno-unused-parameter \
286
287LOCAL_MODULE := adb
288LOCAL_MODULE_TAGS := debug
289LOCAL_MODULE_HOST_OS := darwin linux windows
290
291LOCAL_SANITIZE := $(adb_host_sanitize)
292LOCAL_STATIC_LIBRARIES := \
293 libadb \
294 libbase \
295 libcrypto_utils \
296 libcrypto \
297 libdiagnose_usb \
298 liblog \
299 libmdnssd \
300 libusb \
301
302# Don't use libcutils on Windows.
303LOCAL_STATIC_LIBRARIES_darwin := libcutils
304LOCAL_STATIC_LIBRARIES_linux := libcutils
305
306LOCAL_CXX_STL := libc++_static
307
308# Don't add anything here, we don't want additional shared dependencies
309# on the host adb tool, and shared libraries that link against libc++
310# will violate ODR
311LOCAL_SHARED_LIBRARIES :=
312
313include $(BUILD_HOST_EXECUTABLE)
314
315$(call dist-for-goals,dist_files sdk win_sdk,$(LOCAL_BUILT_MODULE))
316ifdef HOST_CROSS_OS
317# Archive adb.exe for win_sdk build.
318$(call dist-for-goals,win_sdk,$(ALL_MODULES.host_cross_adb.BUILT))
319endif
320
321
322# adbd device daemon
323# =========================================================
324
325include $(CLEAR_VARS)
326
327LOCAL_SRC_FILES := \
328 daemon/main.cpp \
329 daemon/mdns.cpp \
330 services.cpp \
331 file_sync_service.cpp \
332 framebuffer_service.cpp \
333 remount_service.cpp \
334 set_verity_enable_state_service.cpp \
335 shell_service.cpp \
336 shell_service_protocol.cpp \
337
338LOCAL_CFLAGS := \
339 $(ADB_COMMON_CFLAGS) \
340 $(ADB_COMMON_linux_CFLAGS) \
341 -DADB_HOST=0 \
342 -D_GNU_SOURCE \
343 -Wno-deprecated-declarations \
344
345LOCAL_CFLAGS += -DALLOW_ADBD_NO_AUTH=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0)
346
347ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
348LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
349LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
350endif
351
352LOCAL_MODULE := adbd
353
354LOCAL_FORCE_STATIC_EXECUTABLE := true
355
356LOCAL_SANITIZE := $(adb_target_sanitize)
357LOCAL_STRIP_MODULE := keep_symbols
358LOCAL_STATIC_LIBRARIES := \
359 libadbd \
360 libasyncio \
361 libavb_user \
362 libbase \
363 libqemu_pipe \
364 libbootloader_message \
365 libfs_mgr \
366 libfec \
367 libfec_rs \
368 libselinux \
369 liblog \
370 libext4_utils \
371 libsquashfs_utils \
372 libcutils \
373 libbase \
374 libcrypto_utils \
375 libcrypto \
376 libminijail \
377 libmdnssd \
378 libdebuggerd_handler \
379
380include $(BUILD_EXECUTABLE)
381
382# adb integration test
383# =========================================================
384$(call dist-for-goals,sdk,$(ALL_MODULES.adb_integration_test_adb.BUILT))
385$(call dist-for-goals,sdk,$(ALL_MODULES.adb_integration_test_device.BUILT))
386
387include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/adb/CPPLINT.cfg b/adb/CPPLINT.cfg
deleted file mode 100644
index f496490cc..000000000
--- a/adb/CPPLINT.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
1set noparent
2filter=-build/header_guard,-build/include,-readability/function,-whitespace/indent
diff --git a/adb/adb.cpp b/adb/adb.cpp
index ee3503bb3..65fa2e795 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -42,9 +42,9 @@
42#include <android-base/logging.h> 42#include <android-base/logging.h>
43#include <android-base/macros.h> 43#include <android-base/macros.h>
44#include <android-base/parsenetaddress.h> 44#include <android-base/parsenetaddress.h>
45#include <android-base/quick_exit.h>
46#include <android-base/stringprintf.h> 45#include <android-base/stringprintf.h>
47#include <android-base/strings.h> 46#include <android-base/strings.h>
47#include <build/version.h>
48 48
49#include "adb_auth.h" 49#include "adb_auth.h"
50#include "adb_io.h" 50#include "adb_io.h"
@@ -67,8 +67,8 @@ std::string adb_version() {
67 "Android Debug Bridge version %d.%d.%d\n" 67 "Android Debug Bridge version %d.%d.%d\n"
68 "Version %s\n" 68 "Version %s\n"
69 "Installed as %s\n", 69 "Installed as %s\n",
70 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION, ADB_VERSION, 70 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
71 android::base::GetExecutablePath().c_str()); 71 android::build::GetBuildNumber().c_str(), android::base::GetExecutablePath().c_str());
72} 72}
73 73
74void fatal(const char *fmt, ...) { 74void fatal(const char *fmt, ...) {
@@ -105,31 +105,27 @@ void fatal_errno(const char* fmt, ...) {
105} 105}
106 106
107uint32_t calculate_apacket_checksum(const apacket* p) { 107uint32_t calculate_apacket_checksum(const apacket* p) {
108 const unsigned char* x = reinterpret_cast<const unsigned char*>(p->data);
109 uint32_t sum = 0; 108 uint32_t sum = 0;
110 size_t count = p->msg.data_length; 109 for (size_t i = 0; i < p->msg.data_length; ++i) {
111 110 sum += static_cast<uint8_t>(p->payload[i]);
112 while (count-- > 0) {
113 sum += *x++;
114 } 111 }
115
116 return sum; 112 return sum;
117} 113}
118 114
119apacket* get_apacket(void) 115apacket* get_apacket(void)
120{ 116{
121 apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket))); 117 apacket* p = new apacket();
122 if (p == nullptr) { 118 if (p == nullptr) {
123 fatal("failed to allocate an apacket"); 119 fatal("failed to allocate an apacket");
124 } 120 }
125 121
126 memset(p, 0, sizeof(apacket) - MAX_PAYLOAD); 122 memset(&p->msg, 0, sizeof(p->msg));
127 return p; 123 return p;
128} 124}
129 125
130void put_apacket(apacket *p) 126void put_apacket(apacket *p)
131{ 127{
132 free(p); 128 delete p;
133} 129}
134 130
135void handle_online(atransport *t) 131void handle_online(atransport *t)
@@ -140,8 +136,16 @@ void handle_online(atransport *t)
140 136
141void handle_offline(atransport *t) 137void handle_offline(atransport *t)
142{ 138{
143 D("adb: offline"); 139 if (t->GetConnectionState() == kCsOffline) {
144 //Close the associated usb 140 LOG(INFO) << t->serial_name() << ": already offline";
141 return;
142 }
143
144 LOG(INFO) << t->serial_name() << ": offline";
145
146 t->SetConnectionState(kCsOffline);
147
148 // Close the associated usb
145 t->online = 0; 149 t->online = 0;
146 150
147 // This is necessary to avoid a race condition that occurred when a transport closes 151 // This is necessary to avoid a race condition that occurred when a transport closes
@@ -155,8 +159,7 @@ void handle_offline(atransport *t)
155#define DUMPMAX 32 159#define DUMPMAX 32
156void print_packet(const char *label, apacket *p) 160void print_packet(const char *label, apacket *p)
157{ 161{
158 char *tag; 162 const char* tag;
159 char *x;
160 unsigned count; 163 unsigned count;
161 164
162 switch(p->msg.command){ 165 switch(p->msg.command){
@@ -173,15 +176,15 @@ void print_packet(const char *label, apacket *p)
173 fprintf(stderr, "%s: %s %08x %08x %04x \"", 176 fprintf(stderr, "%s: %s %08x %08x %04x \"",
174 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length); 177 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
175 count = p->msg.data_length; 178 count = p->msg.data_length;
176 x = (char*) p->data; 179 const char* x = p->payload.data();
177 if(count > DUMPMAX) { 180 if (count > DUMPMAX) {
178 count = DUMPMAX; 181 count = DUMPMAX;
179 tag = "\n"; 182 tag = "\n";
180 } else { 183 } else {
181 tag = "\"\n"; 184 tag = "\"\n";
182 } 185 }
183 while(count-- > 0){ 186 while (count-- > 0) {
184 if((*x >= ' ') && (*x < 127)) { 187 if ((*x >= ' ') && (*x < 127)) {
185 fputc(*x, stderr); 188 fputc(*x, stderr);
186 } else { 189 } else {
187 fputc('.', stderr); 190 fputc('.', stderr);
@@ -254,8 +257,8 @@ void send_connect(atransport* t) {
254 << connection_str.length() << ")"; 257 << connection_str.length() << ")";
255 } 258 }
256 259
257 memcpy(cp->data, connection_str.c_str(), connection_str.length()); 260 cp->payload = std::move(connection_str);
258 cp->msg.data_length = connection_str.length(); 261 cp->msg.data_length = cp->payload.size();
259 262
260 send_packet(cp, t); 263 send_packet(cp, t);
261} 264}
@@ -323,15 +326,10 @@ void parse_banner(const std::string& banner, atransport* t) {
323} 326}
324 327
325static void handle_new_connection(atransport* t, apacket* p) { 328static void handle_new_connection(atransport* t, apacket* p) {
326 if (t->GetConnectionState() != kCsOffline) { 329 handle_offline(t);
327 t->SetConnectionState(kCsOffline);
328 handle_offline(t);
329 }
330 330
331 t->update_version(p->msg.arg0, p->msg.arg1); 331 t->update_version(p->msg.arg0, p->msg.arg1);
332 std::string banner(reinterpret_cast<const char*>(p->data), 332 parse_banner(p->payload, t);
333 p->msg.data_length);
334 parse_banner(banner, t);
335 333
336#if ADB_HOST 334#if ADB_HOST
337 handle_online(t); 335 handle_online(t);
@@ -354,21 +352,9 @@ void handle_packet(apacket *p, atransport *t)
354 ((char*) (&(p->msg.command)))[2], 352 ((char*) (&(p->msg.command)))[2],
355 ((char*) (&(p->msg.command)))[3]); 353 ((char*) (&(p->msg.command)))[3]);
356 print_packet("recv", p); 354 print_packet("recv", p);
355 CHECK_EQ(p->payload.size(), p->msg.data_length);
357 356
358 switch(p->msg.command){ 357 switch(p->msg.command){
359 case A_SYNC:
360 if (p->msg.arg0){
361 send_packet(p, t);
362#if ADB_HOST
363 send_connect(t);
364#endif
365 } else {
366 t->SetConnectionState(kCsOffline);
367 handle_offline(t);
368 send_packet(p, t);
369 }
370 return;
371
372 case A_CNXN: // CONNECT(version, maxdata, "system-id-string") 358 case A_CNXN: // CONNECT(version, maxdata, "system-id-string")
373 handle_new_connection(t, p); 359 handle_new_connection(t, p);
374 break; 360 break;
@@ -380,11 +366,11 @@ void handle_packet(apacket *p, atransport *t)
380 if (t->GetConnectionState() == kCsOffline) { 366 if (t->GetConnectionState() == kCsOffline) {
381 t->SetConnectionState(kCsUnauthorized); 367 t->SetConnectionState(kCsUnauthorized);
382 } 368 }
383 send_auth_response(p->data, p->msg.data_length, t); 369 send_auth_response(p->payload.data(), p->msg.data_length, t);
384 break; 370 break;
385#else 371#else
386 case ADB_AUTH_SIGNATURE: 372 case ADB_AUTH_SIGNATURE:
387 if (adbd_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) { 373 if (adbd_auth_verify(t->token, sizeof(t->token), p->payload)) {
388 adbd_auth_verified(t); 374 adbd_auth_verified(t);
389 t->failed_auth_attempts = 0; 375 t->failed_auth_attempts = 0;
390 } else { 376 } else {
@@ -394,7 +380,7 @@ void handle_packet(apacket *p, atransport *t)
394 break; 380 break;
395 381
396 case ADB_AUTH_RSAPUBLICKEY: 382 case ADB_AUTH_RSAPUBLICKEY:
397 adbd_auth_confirm_key(p->data, p->msg.data_length, t); 383 adbd_auth_confirm_key(p->payload.data(), p->msg.data_length, t);
398 break; 384 break;
399#endif 385#endif
400 default: 386 default:
@@ -406,9 +392,7 @@ void handle_packet(apacket *p, atransport *t)
406 392
407 case A_OPEN: /* OPEN(local-id, 0, "destination") */ 393 case A_OPEN: /* OPEN(local-id, 0, "destination") */
408 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) { 394 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
409 char *name = (char*) p->data; 395 asocket* s = create_local_service_socket(p->payload.c_str(), t);
410 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
411 asocket* s = create_local_service_socket(name, t);
412 if (s == nullptr) { 396 if (s == nullptr) {
413 send_close(0, p->msg.arg0, t); 397 send_close(0, p->msg.arg0, t);
414 } else { 398 } else {
@@ -474,11 +458,7 @@ void handle_packet(apacket *p, atransport *t)
474 asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0); 458 asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0);
475 if (s) { 459 if (s) {
476 unsigned rid = p->msg.arg0; 460 unsigned rid = p->msg.arg0;
477 461 if (s->enqueue(s, std::move(p->payload)) == 0) {
478 // TODO: Convert apacket::data to a type that we can move out of.
479 std::string copy(p->data, p->data + p->msg.data_length);
480
481 if (s->enqueue(s, std::move(copy)) == 0) {
482 D("Enqueue the socket"); 462 D("Enqueue the socket");
483 send_ready(s->id, rid, t); 463 send_ready(s->id, rid, t);
484 } 464 }
@@ -1071,7 +1051,7 @@ int handle_host_request(const char* service, TransportType type, const char* ser
1071 SendOkay(reply_fd); 1051 SendOkay(reply_fd);
1072 1052
1073 // Rely on process exit to close the socket for us. 1053 // Rely on process exit to close the socket for us.
1074 android::base::quick_exit(0); 1054 exit(0);
1075 } 1055 }
1076 1056
1077 // "transport:" is used for switching transport with a specified serial number 1057 // "transport:" is used for switching transport with a specified serial number
diff --git a/adb/adb.h b/adb/adb.h
index c9c635a8d..a6d04631d 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -74,7 +74,7 @@ struct amessage {
74 74
75struct apacket { 75struct apacket {
76 amessage msg; 76 amessage msg;
77 char data[MAX_PAYLOAD]; 77 std::string payload;
78}; 78};
79 79
80uint32_t calculate_apacket_checksum(const apacket* packet); 80uint32_t calculate_apacket_checksum(const apacket* packet);
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index a6f224f00..715e04f2c 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -49,7 +49,7 @@ void adbd_auth_init(void);
49void adbd_auth_verified(atransport *t); 49void adbd_auth_verified(atransport *t);
50 50
51void adbd_cloexec_auth_socket(); 51void adbd_cloexec_auth_socket();
52bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int sig_len); 52bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig);
53void adbd_auth_confirm_key(const char* data, size_t len, atransport* t); 53void adbd_auth_confirm_key(const char* data, size_t len, atransport* t);
54 54
55void send_auth_request(atransport *t); 55void send_auth_request(atransport *t);
diff --git a/adb/adb_client.cpp b/adb/client/adb_client.cpp
index 849a6e772..849a6e772 100644
--- a/adb/adb_client.cpp
+++ b/adb/client/adb_client.cpp
diff --git a/adb/adb_client.h b/adb/client/adb_client.h
index fca435e38..fca435e38 100644
--- a/adb/adb_client.h
+++ b/adb/client/adb_client.h
diff --git a/adb/adb_auth_host.cpp b/adb/client/auth.cpp
index 365bf77a9..c3aef16d4 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/client/auth.cpp
@@ -299,20 +299,25 @@ std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() {
299 return result; 299 return result;
300} 300}
301 301
302static int adb_auth_sign(RSA* key, const char* token, size_t token_size, char* sig) { 302static std::string adb_auth_sign(RSA* key, const char* token, size_t token_size) {
303 if (token_size != TOKEN_SIZE) { 303 if (token_size != TOKEN_SIZE) {
304 D("Unexpected token size %zd", token_size); 304 D("Unexpected token size %zd", token_size);
305 return 0; 305 return 0;
306 } 306 }
307 307
308 std::string result;
309 result.resize(MAX_PAYLOAD);
310
308 unsigned int len; 311 unsigned int len;
309 if (!RSA_sign(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size, 312 if (!RSA_sign(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
310 reinterpret_cast<uint8_t*>(sig), &len, key)) { 313 reinterpret_cast<uint8_t*>(&result[0]), &len, key)) {
311 return 0; 314 return std::string();
312 } 315 }
313 316
317 result.resize(len);
318
314 D("adb_auth_sign len=%d", len); 319 D("adb_auth_sign len=%d", len);
315 return (int)len; 320 return result;
316} 321}
317 322
318std::string adb_auth_get_userkey() { 323std::string adb_auth_get_userkey() {
@@ -446,13 +451,14 @@ static void send_auth_publickey(atransport* t) {
446 } 451 }
447 452
448 apacket* p = get_apacket(); 453 apacket* p = get_apacket();
449 memcpy(p->data, key.c_str(), key.size() + 1);
450
451 p->msg.command = A_AUTH; 454 p->msg.command = A_AUTH;
452 p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY; 455 p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
453 456
457 p->payload = std::move(key);
458
454 // adbd expects a null-terminated string. 459 // adbd expects a null-terminated string.
455 p->msg.data_length = key.size() + 1; 460 p->payload.push_back('\0');
461 p->msg.data_length = p->payload.size();
456 send_packet(p, t); 462 send_packet(p, t);
457} 463}
458 464
@@ -467,8 +473,8 @@ void send_auth_response(const char* token, size_t token_size, atransport* t) {
467 LOG(INFO) << "Calling send_auth_response"; 473 LOG(INFO) << "Calling send_auth_response";
468 apacket* p = get_apacket(); 474 apacket* p = get_apacket();
469 475
470 int ret = adb_auth_sign(key.get(), token, token_size, p->data); 476 std::string result = adb_auth_sign(key.get(), token, token_size);
471 if (!ret) { 477 if (result.empty()) {
472 D("Error signing the token"); 478 D("Error signing the token");
473 put_apacket(p); 479 put_apacket(p);
474 return; 480 return;
@@ -476,6 +482,7 @@ void send_auth_response(const char* token, size_t token_size, atransport* t) {
476 482
477 p->msg.command = A_AUTH; 483 p->msg.command = A_AUTH;
478 p->msg.arg0 = ADB_AUTH_SIGNATURE; 484 p->msg.arg0 = ADB_AUTH_SIGNATURE;
479 p->msg.data_length = ret; 485 p->payload = std::move(result);
486 p->msg.data_length = p->payload.size();
480 send_packet(p, t); 487 send_packet(p, t);
481} 488}
diff --git a/adb/bugreport.cpp b/adb/client/bugreport.cpp
index abef86a68..abef86a68 100644
--- a/adb/bugreport.cpp
+++ b/adb/client/bugreport.cpp
diff --git a/adb/bugreport.h b/adb/client/bugreport.h
index 413439b74..413439b74 100644
--- a/adb/bugreport.h
+++ b/adb/client/bugreport.h
diff --git a/adb/commandline.cpp b/adb/client/commandline.cpp
index d126f52a5..d126f52a5 100644
--- a/adb/commandline.cpp
+++ b/adb/client/commandline.cpp
diff --git a/adb/commandline.h b/adb/client/commandline.h
index 36cd79841..36cd79841 100644
--- a/adb/commandline.h
+++ b/adb/client/commandline.h
diff --git a/adb/console.cpp b/adb/client/console.cpp
index 9563eacb3..9563eacb3 100644
--- a/adb/console.cpp
+++ b/adb/client/console.cpp
diff --git a/adb/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index 26f8d831c..26f8d831c 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
diff --git a/adb/line_printer.cpp b/adb/client/line_printer.cpp
index 64d10b6ca..64d10b6ca 100644
--- a/adb/line_printer.cpp
+++ b/adb/client/line_printer.cpp
diff --git a/adb/line_printer.h b/adb/client/line_printer.h
index 42345e2d6..42345e2d6 100644
--- a/adb/line_printer.h
+++ b/adb/client/line_printer.h
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index f0d0ce799..31cb8536a 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -28,7 +28,6 @@
28#include <android-base/errors.h> 28#include <android-base/errors.h>
29#include <android-base/file.h> 29#include <android-base/file.h>
30#include <android-base/logging.h> 30#include <android-base/logging.h>
31#include <android-base/quick_exit.h>
32#include <android-base/stringprintf.h> 31#include <android-base/stringprintf.h>
33 32
34#include "adb.h" 33#include "adb.h"
@@ -61,7 +60,7 @@ static void setup_daemon_logging() {
61static BOOL WINAPI ctrlc_handler(DWORD type) { 60static BOOL WINAPI ctrlc_handler(DWORD type) {
62 // TODO: Consider trying to kill a starting up adb server (if we're in 61 // TODO: Consider trying to kill a starting up adb server (if we're in
63 // launch_server) by calling GenerateConsoleCtrlEvent(). 62 // launch_server) by calling GenerateConsoleCtrlEvent().
64 android::base::quick_exit(STATUS_CONTROL_C_EXIT); 63 exit(STATUS_CONTROL_C_EXIT);
65 return TRUE; 64 return TRUE;
66} 65}
67#endif 66#endif
@@ -76,6 +75,12 @@ void adb_server_cleanup() {
76 usb_cleanup(); 75 usb_cleanup();
77} 76}
78 77
78static void intentionally_leak() {
79 void* p = ::operator new(1);
80 // The analyzer is upset about this leaking. NOLINTNEXTLINE
81 LOG(INFO) << "leaking pointer " << p;
82}
83
79int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) { 84int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) {
80#if defined(_WIN32) 85#if defined(_WIN32)
81 // adb start-server starts us up with stdout and stderr hooked up to 86 // adb start-server starts us up with stdout and stderr hooked up to
@@ -95,16 +100,21 @@ int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply
95 SetConsoleCtrlHandler(ctrlc_handler, TRUE); 100 SetConsoleCtrlHandler(ctrlc_handler, TRUE);
96#else 101#else
97 signal(SIGINT, [](int) { 102 signal(SIGINT, [](int) {
98 fdevent_run_on_main_thread([]() { android::base::quick_exit(0); }); 103 fdevent_run_on_main_thread([]() { exit(0); });
99 }); 104 });
100#endif 105#endif
101 106
107 char* leak = getenv("ADB_LEAK");
108 if (leak && strcmp(leak, "1") == 0) {
109 intentionally_leak();
110 }
111
102 if (is_daemon) { 112 if (is_daemon) {
103 close_stdin(); 113 close_stdin();
104 setup_daemon_logging(); 114 setup_daemon_logging();
105 } 115 }
106 116
107 android::base::at_quick_exit(adb_server_cleanup); 117 atexit(adb_server_cleanup);
108 118
109 init_transport_registration(); 119 init_transport_registration();
110 init_mdns_transport_discovery(); 120 init_mdns_transport_discovery();
diff --git a/adb/transport_mdns.cpp b/adb/client/transport_mdns.cpp
index 3603f0974..3603f0974 100644
--- a/adb/transport_mdns.cpp
+++ b/adb/client/transport_mdns.cpp
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 18f585d88..46c3f58ec 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -19,6 +19,7 @@
19#include "sysdeps.h" 19#include "sysdeps.h"
20 20
21#include <stdint.h> 21#include <stdint.h>
22#include <stdlib.h>
22 23
23#include <atomic> 24#include <atomic>
24#include <chrono> 25#include <chrono>
@@ -33,7 +34,6 @@
33 34
34#include <android-base/file.h> 35#include <android-base/file.h>
35#include <android-base/logging.h> 36#include <android-base/logging.h>
36#include <android-base/quick_exit.h>
37#include <android-base/stringprintf.h> 37#include <android-base/stringprintf.h>
38#include <android-base/strings.h> 38#include <android-base/strings.h>
39 39
diff --git a/adb/adbd_auth.cpp b/adb/daemon/auth.cpp
index 3488ad194..3fd2b3194 100644
--- a/adb/adbd_auth.cpp
+++ b/adb/daemon/auth.cpp
@@ -46,7 +46,7 @@ static bool needs_retry = false;
46 46
47bool auth_required = true; 47bool auth_required = true;
48 48
49bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int sig_len) { 49bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig) {
50 static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr }; 50 static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
51 51
52 for (const auto& path : key_paths) { 52 for (const auto& path : key_paths) {
@@ -80,7 +80,8 @@ bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int
80 80
81 bool verified = 81 bool verified =
82 (RSA_verify(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size, 82 (RSA_verify(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
83 reinterpret_cast<const uint8_t*>(sig), sig_len, key) == 1); 83 reinterpret_cast<const uint8_t*>(sig.c_str()), sig.size(),
84 key) == 1);
84 RSA_free(key); 85 RSA_free(key);
85 if (verified) return true; 86 if (verified) return true;
86 } 87 }
@@ -210,10 +211,10 @@ void send_auth_request(atransport* t) {
210 } 211 }
211 212
212 apacket* p = get_apacket(); 213 apacket* p = get_apacket();
213 memcpy(p->data, t->token, sizeof(t->token));
214 p->msg.command = A_AUTH; 214 p->msg.command = A_AUTH;
215 p->msg.arg0 = ADB_AUTH_TOKEN; 215 p->msg.arg0 = ADB_AUTH_TOKEN;
216 p->msg.data_length = sizeof(t->token); 216 p->msg.data_length = sizeof(t->token);
217 p->payload.assign(t->token, t->token + sizeof(t->token));
217 send_packet(p, t); 218 send_packet(p, t);
218} 219}
219 220
diff --git a/adb/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index 9a87931a3..9a87931a3 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
diff --git a/adb/framebuffer_service.cpp b/adb/daemon/framebuffer_service.cpp
index 6c3a2252f..6c3a2252f 100644
--- a/adb/framebuffer_service.cpp
+++ b/adb/daemon/framebuffer_service.cpp
diff --git a/adb/jdwp_service.cpp b/adb/daemon/jdwp_service.cpp
index 6f5396a8f..976155884 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/daemon/jdwp_service.cpp
@@ -128,7 +128,7 @@ static void jdwp_process_event(int socket, unsigned events, void* _proc);
128static void jdwp_process_list_updated(void); 128static void jdwp_process_list_updated(void);
129 129
130struct JdwpProcess; 130struct JdwpProcess;
131static std::list<std::unique_ptr<JdwpProcess>> _jdwp_list; 131static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>();
132 132
133struct JdwpProcess { 133struct JdwpProcess {
134 explicit JdwpProcess(int socket) { 134 explicit JdwpProcess(int socket) {
@@ -511,7 +511,7 @@ struct JdwpTracker : public asocket {
511 bool need_initial; 511 bool need_initial;
512}; 512};
513 513
514static std::vector<std::unique_ptr<JdwpTracker>> _jdwp_trackers; 514static auto& _jdwp_trackers = *new std::vector<std::unique_ptr<JdwpTracker>>();
515 515
516static void jdwp_process_list_updated(void) { 516static void jdwp_process_list_updated(void) {
517 std::string data; 517 std::string data;
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 3c2758276..9b25a0776 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -158,9 +158,9 @@ int adbd_main(int server_port) {
158 // descriptor will always be open. 158 // descriptor will always be open.
159 adbd_cloexec_auth_socket(); 159 adbd_cloexec_auth_socket();
160 160
161 if (ALLOW_ADBD_NO_AUTH && !android::base::GetBoolProperty("ro.adb.secure", false)) { 161#if defined(ALLOW_ADBD_NO_AUTH)
162 auth_required = false; 162 auth_required = android::base::GetBoolProperty("ro.adb.secure", true);
163 } 163#endif
164 164
165 adbd_auth_init(); 165 adbd_auth_init();
166 166
diff --git a/adb/remount_service.cpp b/adb/daemon/remount_service.cpp
index 32ed28f59..a4c7a5a3d 100644
--- a/adb/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -62,9 +62,9 @@ static std::string find_fstab_mount(const char* dir) {
62 62
63// The proc entry for / is full of lies, so check fstab instead. 63// The proc entry for / is full of lies, so check fstab instead.
64// /proc/mounts lists rootfs and /dev/root, neither of which is what we want. 64// /proc/mounts lists rootfs and /dev/root, neither of which is what we want.
65static std::string find_mount(const char* dir) { 65static std::string find_mount(const char* dir, bool is_root) {
66 if (strcmp(dir, "/") == 0) { 66 if (is_root) {
67 return find_fstab_mount(dir); 67 return find_fstab_mount(dir);
68 } else { 68 } else {
69 return find_proc_mount(dir); 69 return find_proc_mount(dir);
70 } 70 }
@@ -86,17 +86,29 @@ static bool remount_partition(int fd, const char* dir) {
86 if (!directory_exists(dir)) { 86 if (!directory_exists(dir)) {
87 return true; 87 return true;
88 } 88 }
89 std::string dev = find_mount(dir); 89 bool is_root = strcmp(dir, "/") == 0;
90 if (dev.empty()) { 90 std::string dev = find_mount(dir, is_root);
91 // Even if the device for the root is not found, we still try to remount it
92 // as rw. This typically only happens when running Android in a container:
93 // the root will almost always be in a loop device, which is dynamic, so
94 // it's not convenient to put in the fstab.
95 if (dev.empty() && !is_root) {
91 return true; 96 return true;
92 } 97 }
93 if (!make_block_device_writable(dev)) { 98 if (!dev.empty() && !make_block_device_writable(dev)) {
94 WriteFdFmt(fd, "remount of %s failed; couldn't make block device %s writable: %s\n", 99 WriteFdFmt(fd, "remount of %s failed; couldn't make block device %s writable: %s\n",
95 dir, dev.c_str(), strerror(errno)); 100 dir, dev.c_str(), strerror(errno));
96 return false; 101 return false;
97 } 102 }
103 if (mount(dev.c_str(), dir, "none", MS_REMOUNT | MS_BIND, nullptr) == -1) {
104 // This is useful for cases where the superblock is already marked as
105 // read-write, but the mount itself is read-only, such as containers
106 // where the remount with just MS_REMOUNT is forbidden by the kernel.
107 WriteFdFmt(fd, "remount of the %s mount failed: %s.\n", dir, strerror(errno));
108 return false;
109 }
98 if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) { 110 if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) {
99 WriteFdFmt(fd, "remount of %s failed: %s\n", dir, strerror(errno)); 111 WriteFdFmt(fd, "remount of the %s superblock failed: %s\n", dir, strerror(errno));
100 return false; 112 return false;
101 } 113 }
102 return true; 114 return true;
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/daemon/set_verity_enable_state_service.cpp
index 49e0363a1..49e0363a1 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/daemon/set_verity_enable_state_service.cpp
diff --git a/adb/shell_service.cpp b/adb/daemon/shell_service.cpp
index f9f80c03d..f9f80c03d 100644
--- a/adb/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
diff --git a/adb/shell_service_test.cpp b/adb/daemon/shell_service_test.cpp
index 839284ed0..839284ed0 100644
--- a/adb/shell_service_test.cpp
+++ b/adb/daemon/shell_service_test.cpp
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index b28de4b52..d2855619b 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -26,6 +26,7 @@
26#include <unistd.h> 26#include <unistd.h>
27 27
28#include <atomic> 28#include <atomic>
29#include <deque>
29#include <functional> 30#include <functional>
30#include <list> 31#include <list>
31#include <mutex> 32#include <mutex>
@@ -81,7 +82,7 @@ static unsigned long main_thread_id;
81 82
82static auto& run_queue_notify_fd = *new unique_fd(); 83static auto& run_queue_notify_fd = *new unique_fd();
83static auto& run_queue_mutex = *new std::mutex(); 84static auto& run_queue_mutex = *new std::mutex();
84static auto& run_queue GUARDED_BY(run_queue_mutex) = *new std::vector<std::function<void()>>(); 85static auto& run_queue GUARDED_BY(run_queue_mutex) = *new std::deque<std::function<void()>>();
85 86
86void check_main_thread() { 87void check_main_thread() {
87 if (main_thread_valid) { 88 if (main_thread_valid) {
@@ -359,11 +360,21 @@ static void fdevent_subproc_setup() {
359} 360}
360#endif // !ADB_HOST 361#endif // !ADB_HOST
361 362
362static void fdevent_run_flush() REQUIRES(run_queue_mutex) { 363static void fdevent_run_flush() EXCLUDES(run_queue_mutex) {
363 for (auto& f : run_queue) { 364 // We need to be careful around reentrancy here, since a function we call can queue up another
364 f(); 365 // function.
366 while (true) {
367 std::function<void()> fn;
368 {
369 std::lock_guard<std::mutex> lock(run_queue_mutex);
370 if (run_queue.empty()) {
371 break;
372 }
373 fn = run_queue.front();
374 run_queue.pop_front();
375 }
376 fn();
365 } 377 }
366 run_queue.clear();
367} 378}
368 379
369static void fdevent_run_func(int fd, unsigned ev, void* /* userdata */) { 380static void fdevent_run_func(int fd, unsigned ev, void* /* userdata */) {
@@ -377,22 +388,23 @@ static void fdevent_run_func(int fd, unsigned ev, void* /* userdata */) {
377 PLOG(FATAL) << "failed to empty run queue notify fd"; 388 PLOG(FATAL) << "failed to empty run queue notify fd";
378 } 389 }
379 390
380 std::lock_guard<std::mutex> lock(run_queue_mutex);
381 fdevent_run_flush(); 391 fdevent_run_flush();
382} 392}
383 393
384static void fdevent_run_setup() { 394static void fdevent_run_setup() {
385 std::lock_guard<std::mutex> lock(run_queue_mutex); 395 {
386 CHECK(run_queue_notify_fd.get() == -1); 396 std::lock_guard<std::mutex> lock(run_queue_mutex);
387 int s[2]; 397 CHECK(run_queue_notify_fd.get() == -1);
388 if (adb_socketpair(s) != 0) { 398 int s[2];
389 PLOG(FATAL) << "failed to create run queue notify socketpair"; 399 if (adb_socketpair(s) != 0) {
390 } 400 PLOG(FATAL) << "failed to create run queue notify socketpair";
401 }
391 402
392 run_queue_notify_fd.reset(s[0]); 403 run_queue_notify_fd.reset(s[0]);
393 fdevent* fde = fdevent_create(s[1], fdevent_run_func, nullptr); 404 fdevent* fde = fdevent_create(s[1], fdevent_run_func, nullptr);
394 CHECK(fde != nullptr); 405 CHECK(fde != nullptr);
395 fdevent_add(fde, FDE_READ); 406 fdevent_add(fde, FDE_READ);
407 }
396 408
397 fdevent_run_flush(); 409 fdevent_run_flush();
398} 410}
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index 86e020957..63cc4d176 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -194,3 +194,31 @@ TEST_F(FdeventTest, run_on_main_thread) {
194 ASSERT_EQ(i, vec[i]); 194 ASSERT_EQ(i, vec[i]);
195 } 195 }
196} 196}
197
198static std::function<void()> make_appender(std::vector<int>* vec, int value) {
199 return [vec, value]() {
200 check_main_thread();
201 if (value == 100) {
202 return;
203 }
204
205 vec->push_back(value);
206 fdevent_run_on_main_thread(make_appender(vec, value + 1));
207 };
208}
209
210TEST_F(FdeventTest, run_on_main_thread_reentrant) {
211 std::vector<int> vec;
212
213 PrepareThread();
214 std::thread thread(fdevent_loop);
215
216 fdevent_run_on_main_thread(make_appender(&vec, 0));
217
218 TerminateThread(thread);
219
220 ASSERT_EQ(100u, vec.size());
221 for (int i = 0; i < 100; ++i) {
222 ASSERT_EQ(i, vec[i]);
223 }
224}
diff --git a/adb/protocol.txt b/adb/protocol.txt
index 55ea87f0e..f4523c4be 100644
--- a/adb/protocol.txt
+++ b/adb/protocol.txt
@@ -183,9 +183,11 @@ requirement, since they will be ignored.
183 183
184Command constant: A_SYNC 184Command constant: A_SYNC
185 185
186The SYNC message is used by the io pump to make sure that stale 186*** obsolete, no longer used ***
187
188The SYNC message was used by the io pump to make sure that stale
187outbound messages are discarded when the connection to the remote side 189outbound messages are discarded when the connection to the remote side
188is broken. It is only used internally to the bridge and never valid 190is broken. It was only used internally to the bridge and never valid
189to send across the wire. 191to send across the wire.
190 192
191* when the connection to the remote side goes offline, the io pump 193* when the connection to the remote side goes offline, the io pump
diff --git a/adb/services.cpp b/adb/services.cpp
index 6dc71cfc4..fe74eb6e4 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -296,6 +296,7 @@ int service_to_fd(const char* name, const atransport* transport) {
296 void* arg = strdup(name + 7); 296 void* arg = strdup(name + 7);
297 if (arg == NULL) return -1; 297 if (arg == NULL) return -1;
298 ret = create_service_thread("reboot", reboot_service, arg); 298 ret = create_service_thread("reboot", reboot_service, arg);
299 if (ret < 0) free(arg);
299 } else if(!strncmp(name, "root:", 5)) { 300 } else if(!strncmp(name, "root:", 5)) {
300 ret = create_service_thread("root", restart_root_service, nullptr); 301 ret = create_service_thread("root", restart_root_service, nullptr);
301 } else if(!strncmp(name, "unroot:", 7)) { 302 } else if(!strncmp(name, "unroot:", 7)) {
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 307cbfe0e..0007fed7b 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -413,15 +413,15 @@ static int remote_socket_enqueue(asocket* s, std::string data) {
413 p->msg.command = A_WRTE; 413 p->msg.command = A_WRTE;
414 p->msg.arg0 = s->peer->id; 414 p->msg.arg0 = s->peer->id;
415 p->msg.arg1 = s->id; 415 p->msg.arg1 = s->id;
416 p->msg.data_length = data.size();
417 416
418 if (data.size() > sizeof(p->data)) { 417 if (data.size() > MAX_PAYLOAD) {
419 put_apacket(p); 418 put_apacket(p);
420 return -1; 419 return -1;
421 } 420 }
422 421
423 // TODO: Convert apacket::data to a type that we can move into. 422 p->payload = std::move(data);
424 memcpy(p->data, data.data(), data.size()); 423 p->msg.data_length = p->payload.size();
424
425 send_packet(p, s->transport); 425 send_packet(p, s->transport);
426 return 1; 426 return 1;
427} 427}
@@ -482,17 +482,20 @@ asocket* create_remote_socket(unsigned id, atransport* t) {
482void connect_to_remote(asocket* s, const char* destination) { 482void connect_to_remote(asocket* s, const char* destination) {
483 D("Connect_to_remote call RS(%d) fd=%d", s->id, s->fd); 483 D("Connect_to_remote call RS(%d) fd=%d", s->id, s->fd);
484 apacket* p = get_apacket(); 484 apacket* p = get_apacket();
485 size_t len = strlen(destination) + 1;
486
487 if (len > (s->get_max_payload() - 1)) {
488 fatal("destination oversized");
489 }
490 485
491 D("LS(%d): connect('%s')", s->id, destination); 486 D("LS(%d): connect('%s')", s->id, destination);
492 p->msg.command = A_OPEN; 487 p->msg.command = A_OPEN;
493 p->msg.arg0 = s->id; 488 p->msg.arg0 = s->id;
494 p->msg.data_length = len; 489
495 strcpy((char*)p->data, destination); 490 // adbd expects a null-terminated string.
491 p->payload = destination;
492 p->payload.push_back('\0');
493 p->msg.data_length = p->payload.size();
494
495 if (p->msg.data_length > s->get_max_payload()) {
496 fatal("destination oversized");
497 }
498
496 send_packet(p, s->transport); 499 send_packet(p, s->transport);
497} 500}
498 501
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 9ae129751..3329f0f19 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -28,23 +28,24 @@
28#include <unistd.h> 28#include <unistd.h>
29 29
30#include <algorithm> 30#include <algorithm>
31#include <deque>
31#include <list> 32#include <list>
32#include <mutex> 33#include <mutex>
33#include <thread> 34#include <thread>
34 35
35#include <android-base/logging.h> 36#include <android-base/logging.h>
36#include <android-base/parsenetaddress.h> 37#include <android-base/parsenetaddress.h>
37#include <android-base/quick_exit.h>
38#include <android-base/stringprintf.h> 38#include <android-base/stringprintf.h>
39#include <android-base/strings.h> 39#include <android-base/strings.h>
40#include <android-base/thread_annotations.h> 40#include <android-base/thread_annotations.h>
41 41
42#include <diagnose_usb.h>
43
42#include "adb.h" 44#include "adb.h"
43#include "adb_auth.h" 45#include "adb_auth.h"
44#include "adb_io.h" 46#include "adb_io.h"
45#include "adb_trace.h" 47#include "adb_trace.h"
46#include "adb_utils.h" 48#include "adb_utils.h"
47#include "diagnose_usb.h"
48#include "fdevent.h" 49#include "fdevent.h"
49 50
50static void transport_unref(atransport *t); 51static void transport_unref(atransport *t);
@@ -66,18 +67,96 @@ TransportId NextTransportId() {
66 return next++; 67 return next++;
67} 68}
68 69
70BlockingConnectionAdapter::BlockingConnectionAdapter(std::unique_ptr<BlockingConnection> connection)
71 : underlying_(std::move(connection)) {}
72
73BlockingConnectionAdapter::~BlockingConnectionAdapter() {
74 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): destructing";
75 Stop();
76}
77
78void BlockingConnectionAdapter::Start() {
79 read_thread_ = std::thread([this]() {
80 LOG(INFO) << this->transport_name_ << ": read thread spawning";
81 while (true) {
82 std::unique_ptr<apacket> packet(new apacket());
83 if (!underlying_->Read(packet.get())) {
84 PLOG(INFO) << this->transport_name_ << ": read failed";
85 break;
86 }
87 read_callback_(this, std::move(packet));
88 }
89 std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "read failed"); });
90 });
91
92 write_thread_ = std::thread([this]() {
93 LOG(INFO) << this->transport_name_ << ": write thread spawning";
94 while (true) {
95 std::unique_lock<std::mutex> lock(mutex_);
96 cv_.wait(lock, [this]() { return this->stopped_ || !this->write_queue_.empty(); });
97
98 if (this->stopped_) {
99 return;
100 }
101
102 std::unique_ptr<apacket> packet = std::move(this->write_queue_.front());
103 this->write_queue_.pop_front();
104 lock.unlock();
105
106 if (!this->underlying_->Write(packet.get())) {
107 break;
108 }
109 }
110 std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "write failed"); });
111 });
112}
113
114void BlockingConnectionAdapter::Stop() {
115 std::unique_lock<std::mutex> lock(mutex_);
116 if (stopped_) {
117 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): already stopped";
118 return;
119 }
120
121 stopped_ = true;
122 lock.unlock();
123
124 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): stopping";
125
126 this->underlying_->Close();
127
128 this->cv_.notify_one();
129 read_thread_.join();
130 write_thread_.join();
131
132 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): stopped";
133 std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "requested stop"); });
134}
135
136bool BlockingConnectionAdapter::Write(std::unique_ptr<apacket> packet) {
137 {
138 std::unique_lock<std::mutex> lock(this->mutex_);
139 write_queue_.emplace_back(std::move(packet));
140 }
141
142 cv_.notify_one();
143 return true;
144}
145
69bool FdConnection::Read(apacket* packet) { 146bool FdConnection::Read(apacket* packet) {
70 if (!ReadFdExactly(fd_.get(), &packet->msg, sizeof(amessage))) { 147 if (!ReadFdExactly(fd_.get(), &packet->msg, sizeof(amessage))) {
71 D("remote local: read terminated (message)"); 148 D("remote local: read terminated (message)");
72 return false; 149 return false;
73 } 150 }
74 151
75 if (packet->msg.data_length > sizeof(packet->data)) { 152 if (packet->msg.data_length > MAX_PAYLOAD) {
76 D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length); 153 D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length);
77 return false; 154 return false;
78 } 155 }
79 156
80 if (!ReadFdExactly(fd_.get(), &packet->data, packet->msg.data_length)) { 157 packet->payload.resize(packet->msg.data_length);
158
159 if (!ReadFdExactly(fd_.get(), &packet->payload[0], packet->payload.size())) {
81 D("remote local: terminated (data)"); 160 D("remote local: terminated (data)");
82 return false; 161 return false;
83 } 162 }
@@ -86,13 +165,18 @@ bool FdConnection::Read(apacket* packet) {
86} 165}
87 166
88bool FdConnection::Write(apacket* packet) { 167bool FdConnection::Write(apacket* packet) {
89 uint32_t length = packet->msg.data_length; 168 if (!WriteFdExactly(fd_.get(), &packet->msg, sizeof(packet->msg))) {
90
91 if (!WriteFdExactly(fd_.get(), &packet->msg, sizeof(amessage) + length)) {
92 D("remote local: write terminated"); 169 D("remote local: write terminated");
93 return false; 170 return false;
94 } 171 }
95 172
173 if (packet->msg.data_length) {
174 if (!WriteFdExactly(fd_.get(), &packet->payload[0], packet->msg.data_length)) {
175 D("remote local: write terminated");
176 return false;
177 }
178 }
179
96 return true; 180 return true;
97} 181}
98 182
@@ -133,70 +217,10 @@ static std::string dump_packet(const char* name, const char* func, apacket* p) {
133 217
134 std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", name, 218 std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", name,
135 func, cmd, arg0, arg1, len); 219 func, cmd, arg0, arg1, len);
136 result += dump_hex(p->data, len); 220 result += dump_hex(p->payload.data(), p->payload.size());
137 return result; 221 return result;
138} 222}
139 223
140static int read_packet(int fd, const char* name, apacket** ppacket) {
141 ATRACE_NAME("read_packet");
142 char buff[8];
143 if (!name) {
144 snprintf(buff, sizeof buff, "fd=%d", fd);
145 name = buff;
146 }
147 char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
148 int len = sizeof(apacket*);
149 while (len > 0) {
150 int r = adb_read(fd, p, len);
151 if (r > 0) {
152 len -= r;
153 p += r;
154 } else {
155 D("%s: read_packet (fd=%d), error ret=%d: %s", name, fd, r, strerror(errno));
156 return -1;
157 }
158 }
159
160 VLOG(TRANSPORT) << dump_packet(name, "from remote", *ppacket);
161 return 0;
162}
163
164static int write_packet(int fd, const char* name, apacket** ppacket) {
165 ATRACE_NAME("write_packet");
166 char buff[8];
167 if (!name) {
168 snprintf(buff, sizeof buff, "fd=%d", fd);
169 name = buff;
170 }
171 VLOG(TRANSPORT) << dump_packet(name, "to remote", *ppacket);
172 char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
173 int len = sizeof(apacket*);
174 while (len > 0) {
175 int r = adb_write(fd, p, len);
176 if (r > 0) {
177 len -= r;
178 p += r;
179 } else {
180 D("%s: write_packet (fd=%d) error ret=%d: %s", name, fd, r, strerror(errno));
181 return -1;
182 }
183 }
184 return 0;
185}
186
187static void transport_socket_events(int fd, unsigned events, void* _t) {
188 atransport* t = reinterpret_cast<atransport*>(_t);
189 D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
190 if (events & FDE_READ) {
191 apacket* p = 0;
192 if (read_packet(fd, t->serial, &p)) {
193 D("%s: failed to read packet from transport socket on fd %d", t->serial, fd);
194 } else {
195 handle_packet(p, (atransport*)_t);
196 }
197 }
198}
199
200void send_packet(apacket* p, atransport* t) { 224void send_packet(apacket* p, atransport* t) {
201 p->msg.magic = p->msg.command ^ 0xffffffff; 225 p->msg.magic = p->msg.command ^ 0xffffffff;
202 // compute a checksum for connection/auth packets for compatibility reasons 226 // compute a checksum for connection/auth packets for compatibility reasons
@@ -206,152 +230,16 @@ void send_packet(apacket* p, atransport* t) {
206 p->msg.data_check = calculate_apacket_checksum(p); 230 p->msg.data_check = calculate_apacket_checksum(p);
207 } 231 }
208 232
209 print_packet("send", p); 233 VLOG(TRANSPORT) << dump_packet(t->serial, "to remote", p);
210 234
211 if (t == NULL) { 235 if (t == NULL) {
212 fatal("Transport is null"); 236 fatal("Transport is null");
213 } 237 }
214 238
215 if (write_packet(t->transport_socket, t->serial, &p)) { 239 if (t->Write(p) != 0) {
216 fatal_errno("cannot enqueue packet on transport socket"); 240 D("%s: failed to enqueue packet, closing transport", t->serial);
217 } 241 t->Kick();
218}
219
220// The transport is opened by transport_register_func before
221// the read_transport and write_transport threads are started.
222//
223// The read_transport thread issues a SYNC(1, token) message to let
224// the write_transport thread know to start things up. In the event
225// of transport IO failure, the read_transport thread will post a
226// SYNC(0,0) message to ensure shutdown.
227//
228// The transport will not actually be closed until both threads exit, but the threads
229// will kick the transport on their way out to disconnect the underlying device.
230//
231// read_transport thread reads data from a transport (representing a usb/tcp connection),
232// and makes the main thread call handle_packet().
233static void read_transport_thread(void* _t) {
234 atransport* t = reinterpret_cast<atransport*>(_t);
235 apacket* p;
236
237 adb_thread_setname(
238 android::base::StringPrintf("<-%s", (t->serial != nullptr ? t->serial : "transport")));
239 D("%s: starting read_transport thread on fd %d, SYNC online (%d)", t->serial, t->fd,
240 t->sync_token + 1);
241 p = get_apacket();
242 p->msg.command = A_SYNC;
243 p->msg.arg0 = 1;
244 p->msg.arg1 = ++(t->sync_token);
245 p->msg.magic = A_SYNC ^ 0xffffffff;
246 if (write_packet(t->fd, t->serial, &p)) {
247 put_apacket(p);
248 D("%s: failed to write SYNC packet", t->serial);
249 goto oops;
250 }
251
252 D("%s: data pump started", t->serial);
253 for (;;) {
254 ATRACE_NAME("read_transport loop");
255 p = get_apacket();
256
257 {
258 ATRACE_NAME("read_transport read_remote");
259 if (!t->connection->Read(p)) {
260 D("%s: remote read failed for transport", t->serial);
261 put_apacket(p);
262 break;
263 }
264
265 if (!check_header(p, t)) {
266 D("%s: remote read: bad header", t->serial);
267 put_apacket(p);
268 break;
269 }
270
271#if ADB_HOST
272 if (p->msg.command == 0) {
273 put_apacket(p);
274 continue;
275 }
276#endif
277 }
278
279 D("%s: received remote packet, sending to transport", t->serial);
280 if (write_packet(t->fd, t->serial, &p)) {
281 put_apacket(p);
282 D("%s: failed to write apacket to transport", t->serial);
283 goto oops;
284 }
285 }
286
287 D("%s: SYNC offline for transport", t->serial);
288 p = get_apacket();
289 p->msg.command = A_SYNC;
290 p->msg.arg0 = 0;
291 p->msg.arg1 = 0;
292 p->msg.magic = A_SYNC ^ 0xffffffff;
293 if (write_packet(t->fd, t->serial, &p)) {
294 put_apacket(p);
295 D("%s: failed to write SYNC apacket to transport", t->serial);
296 }
297
298oops:
299 D("%s: read_transport thread is exiting", t->serial);
300 kick_transport(t);
301 transport_unref(t);
302}
303
304// write_transport thread gets packets sent by the main thread (through send_packet()),
305// and writes to a transport (representing a usb/tcp connection).
306static void write_transport_thread(void* _t) {
307 atransport* t = reinterpret_cast<atransport*>(_t);
308 apacket* p;
309 int active = 0;
310
311 adb_thread_setname(
312 android::base::StringPrintf("->%s", (t->serial != nullptr ? t->serial : "transport")));
313 D("%s: starting write_transport thread, reading from fd %d", t->serial, t->fd);
314
315 for (;;) {
316 ATRACE_NAME("write_transport loop");
317 if (read_packet(t->fd, t->serial, &p)) {
318 D("%s: failed to read apacket from transport on fd %d", t->serial, t->fd);
319 break;
320 }
321
322 if (p->msg.command == A_SYNC) {
323 if (p->msg.arg0 == 0) {
324 D("%s: transport SYNC offline", t->serial);
325 put_apacket(p);
326 break;
327 } else {
328 if (p->msg.arg1 == t->sync_token) {
329 D("%s: transport SYNC online", t->serial);
330 active = 1;
331 } else {
332 D("%s: transport ignoring SYNC %d != %d", t->serial, p->msg.arg1, t->sync_token);
333 }
334 }
335 } else {
336 if (active) {
337 D("%s: transport got packet, sending to remote", t->serial);
338 ATRACE_NAME("write_transport write_remote");
339 if (t->Write(p) != 0) {
340 D("%s: remote write failed for transport", t->serial);
341 put_apacket(p);
342 break;
343 }
344 } else {
345 D("%s: transport ignoring packet while offline", t->serial);
346 }
347 }
348
349 put_apacket(p);
350 } 242 }
351
352 D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
353 kick_transport(t);
354 transport_unref(t);
355} 243}
356 244
357void kick_transport(atransport* t) { 245void kick_transport(atransport* t) {
@@ -544,9 +432,10 @@ static int transport_write_action(int fd, struct tmsg* m) {
544 return 0; 432 return 0;
545} 433}
546 434
547static void transport_registration_func(int _fd, unsigned ev, void* data) { 435static void remove_transport(atransport*);
436
437static void transport_registration_func(int _fd, unsigned ev, void*) {
548 tmsg m; 438 tmsg m;
549 int s[2];
550 atransport* t; 439 atransport* t;
551 440
552 if (!(ev & FDE_READ)) { 441 if (!(ev & FDE_READ)) {
@@ -560,13 +449,7 @@ static void transport_registration_func(int _fd, unsigned ev, void* data) {
560 t = m.transport; 449 t = m.transport;
561 450
562 if (m.action == 0) { 451 if (m.action == 0) {
563 D("transport: %s removing and free'ing %d", t->serial, t->transport_socket); 452 D("transport: %s deleting", t->serial);
564
565 /* IMPORTANT: the remove closes one half of the
566 ** socket pair. The close closes the other half.
567 */
568 fdevent_remove(&(t->transport_fde));
569 adb_close(t->fd);
570 453
571 { 454 {
572 std::lock_guard<std::recursive_mutex> lock(transport_lock); 455 std::lock_guard<std::recursive_mutex> lock(transport_lock);
@@ -588,23 +471,33 @@ static void transport_registration_func(int _fd, unsigned ev, void* data) {
588 /* don't create transport threads for inaccessible devices */ 471 /* don't create transport threads for inaccessible devices */
589 if (t->GetConnectionState() != kCsNoPerm) { 472 if (t->GetConnectionState() != kCsNoPerm) {
590 /* initial references are the two threads */ 473 /* initial references are the two threads */
591 t->ref_count = 2; 474 t->ref_count = 1;
592 475 t->connection->SetTransportName(t->serial_name());
593 if (adb_socketpair(s)) { 476 t->connection->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
594 fatal_errno("cannot open transport socketpair"); 477 if (!check_header(p.get(), t)) {
595 } 478 D("%s: remote read: bad header", t->serial);
596 479 return false;
597 D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]); 480 }
598
599 t->transport_socket = s[0];
600 t->fd = s[1];
601
602 fdevent_install(&(t->transport_fde), t->transport_socket, transport_socket_events, t);
603 481
604 fdevent_set(&(t->transport_fde), FDE_READ); 482 VLOG(TRANSPORT) << dump_packet(t->serial, "from remote", p.get());
483 apacket* packet = p.release();
605 484
606 std::thread(write_transport_thread, t).detach(); 485 // TODO: Does this need to run on the main thread?
607 std::thread(read_transport_thread, t).detach(); 486 fdevent_run_on_main_thread([packet, t]() { handle_packet(packet, t); });
487 return true;
488 });
489 t->connection->SetErrorCallback([t](Connection*, const std::string& error) {
490 D("%s: connection terminated: %s", t->serial, error.c_str());
491 fdevent_run_on_main_thread([t]() {
492 handle_offline(t);
493 transport_unref(t);
494 });
495 });
496
497 t->connection->Start();
498#if ADB_HOST
499 send_connect(t);
500#endif
608 } 501 }
609 502
610 { 503 {
@@ -670,7 +563,7 @@ static void transport_unref(atransport* t) {
670 t->ref_count--; 563 t->ref_count--;
671 if (t->ref_count == 0) { 564 if (t->ref_count == 0) {
672 D("transport: %s unref (kicking and closing)", t->serial); 565 D("transport: %s unref (kicking and closing)", t->serial);
673 t->connection->Close(); 566 t->connection->Stop();
674 remove_transport(t); 567 remove_transport(t);
675 } else { 568 } else {
676 D("transport: %s unref (count=%zu)", t->serial, t->ref_count); 569 D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
@@ -721,9 +614,7 @@ atransport* acquire_one_transport(TransportType type, const char* serial, Transp
721 std::unique_lock<std::recursive_mutex> lock(transport_lock); 614 std::unique_lock<std::recursive_mutex> lock(transport_lock);
722 for (const auto& t : transport_list) { 615 for (const auto& t : transport_list) {
723 if (t->GetConnectionState() == kCsNoPerm) { 616 if (t->GetConnectionState() == kCsNoPerm) {
724#if ADB_HOST
725 *error_out = UsbNoPermissionsLongHelpText(); 617 *error_out = UsbNoPermissionsLongHelpText();
726#endif
727 continue; 618 continue;
728 } 619 }
729 620
@@ -798,14 +689,14 @@ atransport* acquire_one_transport(TransportType type, const char* serial, Transp
798} 689}
799 690
800int atransport::Write(apacket* p) { 691int atransport::Write(apacket* p) {
801 return this->connection->Write(p) ? 0 : -1; 692 return this->connection->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
802} 693}
803 694
804void atransport::Kick() { 695void atransport::Kick() {
805 if (!kicked_) { 696 if (!kicked_) {
806 D("kicking transport %s", this->serial); 697 D("kicking transport %s", this->serial);
807 kicked_ = true; 698 kicked_ = true;
808 this->connection->Close(); 699 this->connection->Stop();
809 } 700 }
810} 701}
811 702
@@ -818,7 +709,7 @@ void atransport::SetConnectionState(ConnectionState state) {
818 connection_state_ = state; 709 connection_state_ = state;
819} 710}
820 711
821const std::string atransport::connection_state_name() const { 712std::string atransport::connection_state_name() const {
822 ConnectionState state = GetConnectionState(); 713 ConnectionState state = GetConnectionState();
823 switch (state) { 714 switch (state) {
824 case kCsOffline: 715 case kCsOffline:
diff --git a/adb/transport.h b/adb/transport.h
index 9700f445b..8b71e3405 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -20,12 +20,14 @@
20#include <sys/types.h> 20#include <sys/types.h>
21 21
22#include <atomic> 22#include <atomic>
23#include <condition_variable>
23#include <deque> 24#include <deque>
24#include <functional> 25#include <functional>
25#include <list> 26#include <list>
26#include <memory> 27#include <memory>
27#include <mutex> 28#include <mutex>
28#include <string> 29#include <string>
30#include <thread>
29#include <unordered_set> 31#include <unordered_set>
30 32
31#include <openssl/rsa.h> 33#include <openssl/rsa.h>
@@ -57,15 +59,47 @@ extern const char* const kFeaturePushSync;
57 59
58TransportId NextTransportId(); 60TransportId NextTransportId();
59 61
60// Abstraction for a blocking packet transport. 62// Abstraction for a non-blocking packet transport.
61struct Connection { 63struct Connection {
62 Connection() = default; 64 Connection() = default;
63 Connection(const Connection& copy) = delete;
64 Connection(Connection&& move) = delete;
65
66 // Destroy a Connection. Formerly known as 'Close' in atransport.
67 virtual ~Connection() = default; 65 virtual ~Connection() = default;
68 66
67 void SetTransportName(std::string transport_name) {
68 transport_name_ = std::move(transport_name);
69 }
70
71 using ReadCallback = std::function<bool(Connection*, std::unique_ptr<apacket>)>;
72 void SetReadCallback(ReadCallback callback) {
73 CHECK(!read_callback_);
74 read_callback_ = callback;
75 }
76
77 // Called after the Connection has terminated, either by an error or because Stop was called.
78 using ErrorCallback = std::function<void(Connection*, const std::string&)>;
79 void SetErrorCallback(ErrorCallback callback) {
80 CHECK(!error_callback_);
81 error_callback_ = callback;
82 }
83
84 virtual bool Write(std::unique_ptr<apacket> packet) = 0;
85
86 virtual void Start() = 0;
87 virtual void Stop() = 0;
88
89 std::string transport_name_;
90 ReadCallback read_callback_;
91 ErrorCallback error_callback_;
92};
93
94// Abstraction for a blocking packet transport.
95struct BlockingConnection {
96 BlockingConnection() = default;
97 BlockingConnection(const BlockingConnection& copy) = delete;
98 BlockingConnection(BlockingConnection&& move) = delete;
99
100 // Destroy a BlockingConnection. Formerly known as 'Close' in atransport.
101 virtual ~BlockingConnection() = default;
102
69 // Read/Write a packet. These functions are concurrently called from a transport's reader/writer 103 // Read/Write a packet. These functions are concurrently called from a transport's reader/writer
70 // threads. 104 // threads.
71 virtual bool Read(apacket* packet) = 0; 105 virtual bool Read(apacket* packet) = 0;
@@ -77,7 +111,30 @@ struct Connection {
77 virtual void Close() = 0; 111 virtual void Close() = 0;
78}; 112};
79 113
80struct FdConnection : public Connection { 114struct BlockingConnectionAdapter : public Connection {
115 explicit BlockingConnectionAdapter(std::unique_ptr<BlockingConnection> connection);
116
117 virtual ~BlockingConnectionAdapter();
118
119 virtual bool Write(std::unique_ptr<apacket> packet) override final;
120
121 virtual void Start() override final;
122 virtual void Stop() override final;
123
124 bool stopped_ = false;
125
126 std::unique_ptr<BlockingConnection> underlying_;
127 std::thread read_thread_;
128 std::thread write_thread_;
129
130 std::deque<std::unique_ptr<apacket>> write_queue_;
131 std::mutex mutex_;
132 std::condition_variable cv_;
133
134 std::once_flag error_flag_;
135};
136
137struct FdConnection : public BlockingConnection {
81 explicit FdConnection(unique_fd fd) : fd_(std::move(fd)) {} 138 explicit FdConnection(unique_fd fd) : fd_(std::move(fd)) {}
82 139
83 bool Read(apacket* packet) override final; 140 bool Read(apacket* packet) override final;
@@ -89,7 +146,7 @@ struct FdConnection : public Connection {
89 unique_fd fd_; 146 unique_fd fd_;
90}; 147};
91 148
92struct UsbConnection : public Connection { 149struct UsbConnection : public BlockingConnection {
93 explicit UsbConnection(usb_handle* handle) : handle_(handle) {} 150 explicit UsbConnection(usb_handle* handle) : handle_(handle) {}
94 ~UsbConnection(); 151 ~UsbConnection();
95 152
@@ -110,7 +167,6 @@ class atransport {
110 167
111 atransport(ConnectionState state = kCsOffline) 168 atransport(ConnectionState state = kCsOffline)
112 : id(NextTransportId()), connection_state_(state) { 169 : id(NextTransportId()), connection_state_(state) {
113 transport_fde = {};
114 // Initialize protocol to min version for compatibility with older versions. 170 // Initialize protocol to min version for compatibility with older versions.
115 // Version will be updated post-connect. 171 // Version will be updated post-connect.
116 protocol_version = A_VERSION_MIN; 172 protocol_version = A_VERSION_MIN;
@@ -126,11 +182,7 @@ class atransport {
126 void SetConnectionState(ConnectionState state); 182 void SetConnectionState(ConnectionState state);
127 183
128 const TransportId id; 184 const TransportId id;
129 int fd = -1;
130 int transport_socket = -1;
131 fdevent transport_fde;
132 size_t ref_count = 0; 185 size_t ref_count = 0;
133 uint32_t sync_token = 0;
134 bool online = false; 186 bool online = false;
135 TransportType type = kTransportAny; 187 TransportType type = kTransportAny;
136 188
@@ -152,8 +204,8 @@ class atransport {
152 char token[TOKEN_SIZE] = {}; 204 char token[TOKEN_SIZE] = {};
153 size_t failed_auth_attempts = 0; 205 size_t failed_auth_attempts = 0;
154 206
155 const std::string serial_name() const { return serial ? serial : "<unknown>"; } 207 std::string serial_name() const { return serial ? serial : "<unknown>"; }
156 const std::string connection_state_name() const; 208 std::string connection_state_name() const;
157 209
158 void update_version(int version, size_t payload); 210 void update_version(int version, size_t payload);
159 int get_protocol_version() const; 211 int get_protocol_version() const;
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 560a0312b..ff395dc7e 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -445,13 +445,14 @@ int init_socket_transport(atransport* t, int s, int adb_port, int local) {
445 int fail = 0; 445 int fail = 0;
446 446
447 unique_fd fd(s); 447 unique_fd fd(s);
448 t->sync_token = 1;
449 t->type = kTransportLocal; 448 t->type = kTransportLocal;
450 449
451#if ADB_HOST 450#if ADB_HOST
452 // Emulator connection. 451 // Emulator connection.
453 if (local) { 452 if (local) {
454 t->connection.reset(new EmulatorConnection(std::move(fd), adb_port)); 453 std::unique_ptr<BlockingConnection> emulator_connection(
454 new EmulatorConnection(std::move(fd), adb_port));
455 t->connection.reset(new BlockingConnectionAdapter(std::move(emulator_connection)));
455 std::lock_guard<std::mutex> lock(local_transports_lock); 456 std::lock_guard<std::mutex> lock(local_transports_lock);
456 atransport* existing_transport = find_emulator_transport_by_adb_port_locked(adb_port); 457 atransport* existing_transport = find_emulator_transport_by_adb_port_locked(adb_port);
457 if (existing_transport != NULL) { 458 if (existing_transport != NULL) {
@@ -470,6 +471,7 @@ int init_socket_transport(atransport* t, int s, int adb_port, int local) {
470#endif 471#endif
471 472
472 // Regular tcp connection. 473 // Regular tcp connection.
473 t->connection.reset(new FdConnection(std::move(fd))); 474 std::unique_ptr<BlockingConnection> fd_connection(new FdConnection(std::move(fd)));
475 t->connection.reset(new BlockingConnectionAdapter(std::move(fd_connection)));
474 return fail; 476 return fail;
475} 477}
diff --git a/adb/transport_mdns_unsupported.cpp b/adb/transport_mdns_unsupported.cpp
deleted file mode 100644
index 387d34132..000000000
--- a/adb/transport_mdns_unsupported.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* For when mDNS discovery is unsupported */
18void init_mdns_transport_discovery(void) {}
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index a1086999d..33e00a1f4 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -61,13 +61,12 @@ static int UsbReadMessage(usb_handle* h, amessage* msg) {
61static int UsbReadPayload(usb_handle* h, apacket* p) { 61static int UsbReadPayload(usb_handle* h, apacket* p) {
62 D("UsbReadPayload(%d)", p->msg.data_length); 62 D("UsbReadPayload(%d)", p->msg.data_length);
63 63
64 if (p->msg.data_length > sizeof(p->data)) { 64 if (p->msg.data_length > MAX_PAYLOAD) {
65 return -1; 65 return -1;
66 } 66 }
67 67
68#if CHECK_PACKET_OVERFLOW 68#if CHECK_PACKET_OVERFLOW
69 size_t usb_packet_size = usb_get_max_packet_size(h); 69 size_t usb_packet_size = usb_get_max_packet_size(h);
70 CHECK_EQ(0ULL, sizeof(p->data) % usb_packet_size);
71 70
72 // Round the data length up to the nearest packet size boundary. 71 // Round the data length up to the nearest packet size boundary.
73 // The device won't send a zero packet for packet size aligned payloads, 72 // The device won't send a zero packet for packet size aligned payloads,
@@ -77,10 +76,18 @@ static int UsbReadPayload(usb_handle* h, apacket* p) {
77 if (rem_size) { 76 if (rem_size) {
78 len += usb_packet_size - rem_size; 77 len += usb_packet_size - rem_size;
79 } 78 }
80 CHECK_LE(len, sizeof(p->data)); 79
81 return usb_read(h, &p->data, len); 80 p->payload.resize(len);
81 int rc = usb_read(h, &p->payload[0], p->payload.size());
82 if (rc != static_cast<int>(p->msg.data_length)) {
83 return -1;
84 }
85
86 p->payload.resize(rc);
87 return rc;
82#else 88#else
83 return usb_read(h, &p->data, p->msg.data_length); 89 p->payload.resize(p->msg.data_length);
90 return usb_read(h, &p->payload[0], p->payload.size());
84#endif 91#endif
85} 92}
86 93
@@ -120,12 +127,13 @@ static int remote_read(apacket* p, usb_handle* usb) {
120 } 127 }
121 128
122 if (p->msg.data_length) { 129 if (p->msg.data_length) {
123 if (p->msg.data_length > sizeof(p->data)) { 130 if (p->msg.data_length > MAX_PAYLOAD) {
124 PLOG(ERROR) << "remote usb: read overflow (data length = " << p->msg.data_length << ")"; 131 PLOG(ERROR) << "remote usb: read overflow (data length = " << p->msg.data_length << ")";
125 return -1; 132 return -1;
126 } 133 }
127 134
128 if (usb_read(usb, p->data, p->msg.data_length)) { 135 p->payload.resize(p->msg.data_length);
136 if (usb_read(usb, &p->payload[0], p->payload.size())) {
129 PLOG(ERROR) << "remote usb: terminated (data)"; 137 PLOG(ERROR) << "remote usb: terminated (data)";
130 return -1; 138 return -1;
131 } 139 }
@@ -152,7 +160,7 @@ bool UsbConnection::Write(apacket* packet) {
152 return false; 160 return false;
153 } 161 }
154 162
155 if (packet->msg.data_length != 0 && usb_write(handle_, &packet->data, size) != 0) { 163 if (packet->msg.data_length != 0 && usb_write(handle_, packet->payload.data(), size) != 0) {
156 PLOG(ERROR) << "remote usb: 2 - write terminated"; 164 PLOG(ERROR) << "remote usb: 2 - write terminated";
157 return false; 165 return false;
158 } 166 }
@@ -166,8 +174,8 @@ void UsbConnection::Close() {
166 174
167void init_usb_transport(atransport* t, usb_handle* h) { 175void init_usb_transport(atransport* t, usb_handle* h) {
168 D("transport: usb"); 176 D("transport: usb");
169 t->connection.reset(new UsbConnection(h)); 177 std::unique_ptr<BlockingConnection> connection(new UsbConnection(h));
170 t->sync_token = 1; 178 t->connection.reset(new BlockingConnectionAdapter(std::move(connection)));
171 t->type = kTransportUsb; 179 t->type = kTransportUsb;
172} 180}
173 181
diff --git a/base/Android.bp b/base/Android.bp
index 6cadcfc0f..5d70d47bd 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -15,8 +15,12 @@
15// 15//
16 16
17cc_defaults { 17cc_defaults {
18 name: "libbase_defaults", 18 name: "libbase_cflags_defaults",
19 cflags: ["-Wall", "-Werror", "-Wextra"], 19 cflags: [
20 "-Wall",
21 "-Werror",
22 "-Wextra",
23 ],
20} 24}
21 25
22cc_library_headers { 26cc_library_headers {
@@ -35,15 +39,9 @@ cc_library_headers {
35 }, 39 },
36} 40}
37 41
38cc_library { 42cc_defaults {
39 name: "libbase", 43 name: "libbase_defaults",
40 defaults: ["libbase_defaults"], 44 defaults: ["libbase_cflags_defaults"],
41 vendor_available: true,
42 host_supported: true,
43 vndk: {
44 enabled: true,
45 support_system_process: true,
46 },
47 srcs: [ 45 srcs: [
48 "chrono_utils.cpp", 46 "chrono_utils.cpp",
49 "file.cpp", 47 "file.cpp",
@@ -55,11 +53,6 @@ cc_library {
55 "test_utils.cpp", 53 "test_utils.cpp",
56 ], 54 ],
57 55
58 header_libs: [
59 "libbase_headers",
60 ],
61 export_header_lib_headers: ["libbase_headers"],
62
63 shared_libs: ["liblog"], 56 shared_libs: ["liblog"],
64 target: { 57 target: {
65 android: { 58 android: {
@@ -96,11 +89,34 @@ cc_library {
96 }, 89 },
97} 90}
98 91
92cc_library {
93 name: "libbase",
94 defaults: ["libbase_defaults"],
95 vendor_available: true,
96 host_supported: true,
97 vndk: {
98 enabled: true,
99 support_system_process: true,
100 },
101 header_libs: [
102 "libbase_headers",
103 ],
104 export_header_lib_headers: ["libbase_headers"],
105}
106
107cc_library_static {
108 name: "libbase_ndk",
109 defaults: ["libbase_defaults"],
110 sdk_version: "current",
111 stl: "c++_static",
112 export_include_dirs: ["include"],
113}
114
99// Tests 115// Tests
100// ------------------------------------------------------------------------------ 116// ------------------------------------------------------------------------------
101cc_test { 117cc_test {
102 name: "libbase_test", 118 name: "libbase_test",
103 defaults: ["libbase_defaults"], 119 defaults: ["libbase_cflags_defaults"],
104 host_supported: true, 120 host_supported: true,
105 srcs: [ 121 srcs: [
106 "endian_test.cpp", 122 "endian_test.cpp",
diff --git a/base/include/android-base/strings.h b/base/include/android-base/strings.h
index c11acb10d..4d9fa3404 100644
--- a/base/include/android-base/strings.h
+++ b/base/include/android-base/strings.h
@@ -67,8 +67,8 @@ bool StartsWithIgnoreCase(const std::string& s, const std::string& prefix);
67// TODO: string_view 67// TODO: string_view
68bool EndsWith(const std::string& s, const char* suffix); 68bool EndsWith(const std::string& s, const char* suffix);
69bool EndsWithIgnoreCase(const std::string& s, const char* suffix); 69bool EndsWithIgnoreCase(const std::string& s, const char* suffix);
70bool EndsWith(const std::string& s, const std::string& prefix); 70bool EndsWith(const std::string& s, const std::string& suffix);
71bool EndsWithIgnoreCase(const std::string& s, const std::string& prefix); 71bool EndsWithIgnoreCase(const std::string& s, const std::string& suffix);
72 72
73// Tests whether 'lhs' equals 'rhs', ignoring case. 73// Tests whether 'lhs' equals 'rhs', ignoring case.
74bool EqualsIgnoreCase(const std::string& lhs, const std::string& rhs); 74bool EqualsIgnoreCase(const std::string& lhs, const std::string& rhs);
diff --git a/base/logging.cpp b/base/logging.cpp
index 0f2012a09..1f7bc2ab9 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -45,7 +45,7 @@
45 45
46// Headers for LogMessage::LogLine. 46// Headers for LogMessage::LogLine.
47#ifdef __ANDROID__ 47#ifdef __ANDROID__
48#include <log/log.h> 48#include <android/log.h>
49#include <android/set_abort_message.h> 49#include <android/set_abort_message.h>
50#else 50#else
51#include <sys/types.h> 51#include <sys/types.h>
diff --git a/base/properties.cpp b/base/properties.cpp
index cde4d69e3..6cf43f9e2 100644
--- a/base/properties.cpp
+++ b/base/properties.cpp
@@ -23,12 +23,11 @@
23 23
24#include <algorithm> 24#include <algorithm>
25#include <chrono> 25#include <chrono>
26#include <limits>
26#include <string> 27#include <string>
27 28
28#include <android-base/parseint.h> 29#include <android-base/parseint.h>
29 30
30using namespace std::chrono_literals;
31
32namespace android { 31namespace android {
33namespace base { 32namespace base {
34 33
@@ -109,7 +108,7 @@ static void WaitForPropertyCallback(void* data_ptr, const char*, const char* val
109static void DurationToTimeSpec(timespec& ts, const std::chrono::milliseconds d) { 108static void DurationToTimeSpec(timespec& ts, const std::chrono::milliseconds d) {
110 auto s = std::chrono::duration_cast<std::chrono::seconds>(d); 109 auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
111 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d - s); 110 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d - s);
112 ts.tv_sec = s.count(); 111 ts.tv_sec = std::min<std::chrono::seconds::rep>(s.count(), std::numeric_limits<time_t>::max());
113 ts.tv_nsec = ns.count(); 112 ts.tv_nsec = ns.count();
114} 113}
115 114
diff --git a/bootstat/Android.bp b/bootstat/Android.bp
index 2c870182c..dd9ba88c2 100644
--- a/bootstat/Android.bp
+++ b/bootstat/Android.bp
@@ -66,6 +66,9 @@ cc_binary {
66 shared_libs: ["liblogcat"], 66 shared_libs: ["liblogcat"],
67 init_rc: ["bootstat.rc"], 67 init_rc: ["bootstat.rc"],
68 product_variables: { 68 product_variables: {
69 pdk: {
70 enabled: false,
71 },
69 debuggable: { 72 debuggable: {
70 init_rc: ["bootstat-debug.rc"], 73 init_rc: ["bootstat-debug.rc"],
71 }, 74 },
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 532352410..7e6f24d15 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -16,7 +16,7 @@ cc_defaults {
16 16
17cc_library_headers { 17cc_library_headers {
18 name: "libdebuggerd_common_headers", 18 name: "libdebuggerd_common_headers",
19 export_include_dirs: ["common/include"] 19 export_include_dirs: ["common/include"],
20} 20}
21 21
22cc_library_shared { 22cc_library_shared {
@@ -39,7 +39,7 @@ cc_library_shared {
39 ], 39 ],
40 40
41 export_header_lib_headers: ["libdebuggerd_common_headers"], 41 export_header_lib_headers: ["libdebuggerd_common_headers"],
42 export_include_dirs: ["tombstoned/include"] 42 export_include_dirs: ["tombstoned/include"],
43} 43}
44 44
45// Utility library to tombstoned and get an output fd. 45// Utility library to tombstoned and get an output fd.
@@ -60,7 +60,7 @@ cc_library_static {
60 ], 60 ],
61 61
62 export_header_lib_headers: ["libdebuggerd_common_headers"], 62 export_header_lib_headers: ["libdebuggerd_common_headers"],
63 export_include_dirs: ["tombstoned/include"] 63 export_include_dirs: ["tombstoned/include"],
64} 64}
65 65
66// Core implementation, linked into libdebuggerd_handler and the dynamic linker. 66// Core implementation, linked into libdebuggerd_handler and the dynamic linker.
@@ -186,7 +186,10 @@ cc_test {
186 "client/debuggerd_client_test.cpp", 186 "client/debuggerd_client_test.cpp",
187 "debuggerd_test.cpp", 187 "debuggerd_test.cpp",
188 ], 188 ],
189 static_libs: ["libasync_safe", "libtombstoned_client_static"], 189 static_libs: [
190 "libasync_safe",
191 "libtombstoned_client_static",
192 ],
190 }, 193 },
191 }, 194 },
192 195
@@ -197,7 +200,7 @@ cc_test {
197 "libdebuggerd_client", 200 "libdebuggerd_client",
198 "liblog", 201 "liblog",
199 "libminijail", 202 "libminijail",
200 "libnativehelper" 203 "libnativehelper",
201 ], 204 ],
202 205
203 static_libs: [ 206 static_libs: [
@@ -298,7 +301,7 @@ cc_binary {
298 "liblog", 301 "liblog",
299 ], 302 ],
300 303
301 init_rc: ["tombstoned/tombstoned.rc"] 304 init_rc: ["tombstoned/tombstoned.rc"],
302} 305}
303 306
304subdirs = [ 307subdirs = [
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 3bc174250..c03b41d2e 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -20,4 +20,5 @@ LOCAL_SRC_FILES_arm := seccomp_policy/crash_dump.arm.policy
20LOCAL_SRC_FILES_arm64 := seccomp_policy/crash_dump.arm64.policy 20LOCAL_SRC_FILES_arm64 := seccomp_policy/crash_dump.arm64.policy
21LOCAL_SRC_FILES_x86 := seccomp_policy/crash_dump.x86.policy 21LOCAL_SRC_FILES_x86 := seccomp_policy/crash_dump.x86.policy
22LOCAL_SRC_FILES_x86_64 := seccomp_policy/crash_dump.x86_64.policy 22LOCAL_SRC_FILES_x86_64 := seccomp_policy/crash_dump.x86_64.policy
23LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
23include $(BUILD_PREBUILT) 24include $(BUILD_PREBUILT)
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index f8b4bad6e..397ff2f11 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -20,6 +20,7 @@
20#include <sys/capability.h> 20#include <sys/capability.h>
21#include <sys/prctl.h> 21#include <sys/prctl.h>
22#include <sys/ptrace.h> 22#include <sys/ptrace.h>
23#include <sys/resource.h>
23#include <sys/syscall.h> 24#include <sys/syscall.h>
24#include <sys/types.h> 25#include <sys/types.h>
25#include <unistd.h> 26#include <unistd.h>
@@ -570,7 +571,7 @@ TEST_F(CrasherTest, fake_pid) {
570static const char* const kDebuggerdSeccompPolicy = 571static const char* const kDebuggerdSeccompPolicy =
571 "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy"; 572 "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
572 573
573pid_t seccomp_fork() { 574static pid_t seccomp_fork_impl(void (*prejail)()) {
574 unique_fd policy_fd(open(kDebuggerdSeccompPolicy, O_RDONLY | O_CLOEXEC)); 575 unique_fd policy_fd(open(kDebuggerdSeccompPolicy, O_RDONLY | O_CLOEXEC));
575 if (policy_fd == -1) { 576 if (policy_fd == -1) {
576 LOG(FATAL) << "failed to open policy " << kDebuggerdSeccompPolicy; 577 LOG(FATAL) << "failed to open policy " << kDebuggerdSeccompPolicy;
@@ -607,10 +608,18 @@ pid_t seccomp_fork() {
607 continue; 608 continue;
608 } 609 }
609 610
611 if (prejail) {
612 prejail();
613 }
614
610 minijail_enter(jail.get()); 615 minijail_enter(jail.get());
611 return result; 616 return result;
612} 617}
613 618
619static pid_t seccomp_fork() {
620 return seccomp_fork_impl(nullptr);
621}
622
614TEST_F(CrasherTest, seccomp_crash) { 623TEST_F(CrasherTest, seccomp_crash) {
615 int intercept_result; 624 int intercept_result;
616 unique_fd output_fd; 625 unique_fd output_fd;
@@ -628,6 +637,46 @@ TEST_F(CrasherTest, seccomp_crash) {
628 ASSERT_BACKTRACE_FRAME(result, "abort"); 637 ASSERT_BACKTRACE_FRAME(result, "abort");
629} 638}
630 639
640static pid_t seccomp_fork_rlimit() {
641 return seccomp_fork_impl([]() {
642 struct rlimit rlim = {
643 .rlim_cur = 512 * 1024 * 1024,
644 .rlim_max = 512 * 1024 * 1024,
645 };
646
647 if (setrlimit(RLIMIT_AS, &rlim) != 0) {
648 raise(SIGINT);
649 }
650 });
651}
652
653TEST_F(CrasherTest, seccomp_crash_oom) {
654 int intercept_result;
655 unique_fd output_fd;
656
657 StartProcess(
658 []() {
659 std::vector<void*> vec;
660 for (int i = 0; i < 512; ++i) {
661 char* buf = static_cast<char*>(malloc(1024 * 1024));
662 if (!buf) {
663 abort();
664 }
665 memset(buf, 0xff, 1024 * 1024);
666 vec.push_back(buf);
667 }
668 },
669 &seccomp_fork_rlimit);
670
671 StartIntercept(&output_fd);
672 FinishCrasher();
673 AssertDeath(SIGABRT);
674 FinishIntercept(&intercept_result);
675 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
676
677 // We can't actually generate a backtrace, just make sure that the process terminates.
678}
679
631__attribute__((noinline)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) { 680__attribute__((noinline)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
632 siginfo_t siginfo; 681 siginfo_t siginfo;
633 siginfo.si_code = SI_QUEUE; 682 siginfo.si_code = SI_QUEUE;
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 364fca5e8..dea2e17eb 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -37,6 +37,7 @@
37 37
38#include <atomic> 38#include <atomic>
39#include <memory> 39#include <memory>
40#include <mutex>
40 41
41#include <android-base/file.h> 42#include <android-base/file.h>
42#include <android-base/unique_fd.h> 43#include <android-base/unique_fd.h>
@@ -298,11 +299,13 @@ exit:
298static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) { 299static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) {
299 // Only allow one thread to handle a crash at a time (this can happen multiple times without 300 // Only allow one thread to handle a crash at a time (this can happen multiple times without
300 // exit, since tombstones can be requested without a real crash happening.) 301 // exit, since tombstones can be requested without a real crash happening.)
301 static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER; 302 static std::recursive_mutex crash_mutex;
302 int ret = pthread_mutex_lock(&crash_mutex); 303 static int lock_count;
303 if (ret != 0) { 304
304 async_safe_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret)); 305 crash_mutex.lock();
305 return; 306 if (lock_count++ > 0) {
307 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "recursed signal handler call, exiting");
308 _exit(1);
306 } 309 }
307 310
308 unique_fd tombstone_socket, output_fd; 311 unique_fd tombstone_socket, output_fd;
@@ -313,7 +316,8 @@ static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_mes
313 tombstoned_notify_completion(tombstone_socket.get()); 316 tombstoned_notify_completion(tombstone_socket.get());
314 } 317 }
315 318
316 pthread_mutex_unlock(&crash_mutex); 319 --lock_count;
320 crash_mutex.unlock();
317} 321}
318 322
319extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext, 323extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext,
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 0f049fd25..7b04e7192 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -68,7 +68,7 @@ namespace unwindstack {
68class Memory; 68class Memory;
69} 69}
70 70
71void dump_memory(log_t* log, unwindstack::Memory* backtrace, uint64_t addr, const char* fmt, ...); 71void dump_memory(log_t* log, unwindstack::Memory* backtrace, uint64_t addr, const std::string&);
72 72
73void read_with_default(const char* path, char* buf, size_t len, const char* default_value); 73void read_with_default(const char* path, char* buf, size_t len, const char* default_value);
74 74
diff --git a/debuggerd/libdebuggerd/test/dump_memory_test.cpp b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
index 7c8a0ea14..be395824b 100644
--- a/debuggerd/libdebuggerd/test/dump_memory_test.cpp
+++ b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
@@ -201,7 +201,7 @@ TEST_F(DumpMemoryTest, aligned_addr) {
201 } 201 }
202 memory_mock_->SetReadData(buffer, sizeof(buffer)); 202 memory_mock_->SetReadData(buffer, sizeof(buffer));
203 203
204 dump_memory(&log_, memory_mock_.get(), 0x12345678, "memory near %.2s:", "r1"); 204 dump_memory(&log_, memory_mock_.get(), 0x12345678, "memory near r1");
205 205
206 std::string tombstone_contents; 206 std::string tombstone_contents;
207 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 207 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -221,7 +221,7 @@ TEST_F(DumpMemoryTest, partial_read) {
221 memory_mock_->SetReadData(buffer, sizeof(buffer)); 221 memory_mock_->SetReadData(buffer, sizeof(buffer));
222 memory_mock_->SetPartialReadAmount(96); 222 memory_mock_->SetPartialReadAmount(96);
223 223
224 dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near %.2s:", "r1"); 224 dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near r1");
225 225
226 std::string tombstone_contents; 226 std::string tombstone_contents;
227 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 227 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -240,7 +240,7 @@ TEST_F(DumpMemoryTest, unaligned_addr) {
240 } 240 }
241 memory_mock_->SetReadData(buffer, sizeof(buffer)); 241 memory_mock_->SetReadData(buffer, sizeof(buffer));
242 242
243 dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near %.2s:", "r1"); 243 dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near r1");
244 244
245 std::string tombstone_contents; 245 std::string tombstone_contents;
246 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 246 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -253,7 +253,7 @@ TEST_F(DumpMemoryTest, unaligned_addr) {
253} 253}
254 254
255TEST_F(DumpMemoryTest, memory_unreadable) { 255TEST_F(DumpMemoryTest, memory_unreadable) {
256 dump_memory(&log_, memory_mock_.get(), 0xa2345678, "memory near pc:"); 256 dump_memory(&log_, memory_mock_.get(), 0xa2345678, "memory near pc");
257 257
258 std::string tombstone_contents; 258 std::string tombstone_contents;
259 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 259 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -309,7 +309,7 @@ TEST_F(DumpMemoryTest, memory_partially_unreadable) {
309 } 309 }
310 memory_mock_->SetReadData(buffer, sizeof(buffer)); 310 memory_mock_->SetReadData(buffer, sizeof(buffer));
311 311
312 dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc:"); 312 dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
313 313
314 std::string tombstone_contents; 314 std::string tombstone_contents;
315 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 315 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -329,7 +329,7 @@ TEST_F(DumpMemoryTest, memory_partially_unreadable_unaligned_return) {
329 memory_mock_->SetReadData(buffer, sizeof(buffer)); 329 memory_mock_->SetReadData(buffer, sizeof(buffer));
330 memory_mock_->SetPartialReadAmount(102); 330 memory_mock_->SetPartialReadAmount(102);
331 331
332 dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc:"); 332 dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
333 333
334 std::string tombstone_contents; 334 std::string tombstone_contents;
335 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 335 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -354,7 +354,7 @@ TEST_F(DumpMemoryTest, memory_partially_unreadable_two_unaligned_reads) {
354 memory_mock_->SetReadData(buffer, sizeof(buffer)); 354 memory_mock_->SetReadData(buffer, sizeof(buffer));
355 memory_mock_->SetPartialReadAmount(45); 355 memory_mock_->SetPartialReadAmount(45);
356 356
357 dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc:"); 357 dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
358 358
359 std::string tombstone_contents; 359 std::string tombstone_contents;
360 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 360 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -380,7 +380,7 @@ TEST_F(DumpMemoryTest, address_low_fence) {
380 memset(buffer, 0, sizeof(buffer)); 380 memset(buffer, 0, sizeof(buffer));
381 memory_mock_->SetReadData(buffer, sizeof(buffer)); 381 memory_mock_->SetReadData(buffer, sizeof(buffer));
382 382
383 dump_memory(&log_, memory_mock_.get(), 0x1000, "memory near %.2s:", "r1"); 383 dump_memory(&log_, memory_mock_.get(), 0x1000, "memory near r1");
384 384
385 std::string tombstone_contents; 385 std::string tombstone_contents;
386 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 386 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -434,7 +434,7 @@ TEST_F(DumpMemoryTest, memory_address_too_low) {
434 memset(buffer, 0, sizeof(buffer)); 434 memset(buffer, 0, sizeof(buffer));
435 memory_mock_->SetReadData(buffer, sizeof(buffer)); 435 memory_mock_->SetReadData(buffer, sizeof(buffer));
436 436
437 dump_memory(&log_, memory_mock_.get(), 0, "memory near %.2s:", "r1"); 437 dump_memory(&log_, memory_mock_.get(), 0, "memory near r1");
438 438
439 std::string tombstone_contents; 439 std::string tombstone_contents;
440 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 440 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -452,13 +452,13 @@ TEST_F(DumpMemoryTest, memory_address_too_high) {
452 memory_mock_->SetReadData(buffer, sizeof(buffer)); 452 memory_mock_->SetReadData(buffer, sizeof(buffer));
453 453
454#if defined(__LP64__) 454#if defined(__LP64__)
455 dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL, "memory near %.2s:", "r1"); 455 dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL, "memory near r1");
456 dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 32, "memory near %.2s:", "r1"); 456 dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 32, "memory near r1");
457 dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 216, "memory near %.2s:", "r1"); 457 dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 216, "memory near r1");
458#else 458#else
459 dump_memory(&log_, memory_mock_.get(), 0xffff0000, "memory near %.2s:", "r1"); 459 dump_memory(&log_, memory_mock_.get(), 0xffff0000, "memory near r1");
460 dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 32, "memory near %.2s:", "r1"); 460 dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 32, "memory near r1");
461 dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 220, "memory near %.2s:", "r1"); 461 dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 220, "memory near r1");
462#endif 462#endif
463 463
464 std::string tombstone_contents; 464 std::string tombstone_contents;
@@ -477,9 +477,9 @@ TEST_F(DumpMemoryTest, memory_address_would_overflow) {
477 memory_mock_->SetReadData(buffer, sizeof(buffer)); 477 memory_mock_->SetReadData(buffer, sizeof(buffer));
478 478
479#if defined(__LP64__) 479#if defined(__LP64__)
480 dump_memory(&log_, memory_mock_.get(), 0xfffffffffffffff0, "memory near %.2s:", "r1"); 480 dump_memory(&log_, memory_mock_.get(), 0xfffffffffffffff0, "memory near r1");
481#else 481#else
482 dump_memory(&log_, memory_mock_.get(), 0xfffffff0, "memory near %.2s:", "r1"); 482 dump_memory(&log_, memory_mock_.get(), 0xfffffff0, "memory near r1");
483#endif 483#endif
484 484
485 std::string tombstone_contents; 485 std::string tombstone_contents;
@@ -500,9 +500,9 @@ TEST_F(DumpMemoryTest, memory_address_nearly_too_high) {
500 memory_mock_->SetReadData(buffer, sizeof(buffer)); 500 memory_mock_->SetReadData(buffer, sizeof(buffer));
501 501
502#if defined(__LP64__) 502#if defined(__LP64__)
503 dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 224, "memory near %.2s:", "r4"); 503 dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 224, "memory near r4");
504#else 504#else
505 dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 224, "memory near %.2s:", "r4"); 505 dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 224, "memory near r4");
506#endif 506#endif
507 507
508 std::string tombstone_contents; 508 std::string tombstone_contents;
@@ -562,7 +562,7 @@ TEST_F(DumpMemoryTest, first_read_empty) {
562 562
563 size_t page_size = sysconf(_SC_PAGE_SIZE); 563 size_t page_size = sysconf(_SC_PAGE_SIZE);
564 uintptr_t addr = 0x10000020 + page_size - 120; 564 uintptr_t addr = 0x10000020 + page_size - 120;
565 dump_memory(&log_, memory_mock_.get(), addr, "memory near %.2s:", "r4"); 565 dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
566 566
567 std::string tombstone_contents; 567 std::string tombstone_contents;
568 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 568 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -621,7 +621,7 @@ TEST_F(DumpMemoryTest, first_read_empty_second_read_stops) {
621 621
622 size_t page_size = sysconf(_SC_PAGE_SIZE); 622 size_t page_size = sysconf(_SC_PAGE_SIZE);
623 uintptr_t addr = 0x10000020 + page_size - 192; 623 uintptr_t addr = 0x10000020 + page_size - 192;
624 dump_memory(&log_, memory_mock_.get(), addr, "memory near %.2s:", "r4"); 624 dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
625 625
626 std::string tombstone_contents; 626 std::string tombstone_contents;
627 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 627 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -679,7 +679,7 @@ TEST_F(DumpMemoryTest, first_read_empty_next_page_out_of_range) {
679 memory_mock_->SetPartialReadAmount(0); 679 memory_mock_->SetPartialReadAmount(0);
680 680
681 uintptr_t addr = 0x10000020; 681 uintptr_t addr = 0x10000020;
682 dump_memory(&log_, memory_mock_.get(), addr, "memory near %.2s:", "r4"); 682 dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
683 683
684 std::string tombstone_contents; 684 std::string tombstone_contents;
685 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 685 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -739,7 +739,7 @@ TEST_F(DumpMemoryTest, first_read_empty_next_page_out_of_range_fence_post) {
739 size_t page_size = sysconf(_SC_PAGE_SIZE); 739 size_t page_size = sysconf(_SC_PAGE_SIZE);
740 uintptr_t addr = 0x10000020 + page_size - 256; 740 uintptr_t addr = 0x10000020 + page_size - 256;
741 741
742 dump_memory(&log_, memory_mock_.get(), addr, "memory near %.2s:", "r4"); 742 dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
743 743
744 std::string tombstone_contents; 744 std::string tombstone_contents;
745 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 745 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 7d8560213..140ef6d23 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -65,6 +65,8 @@ using android::base::unique_fd;
65using unwindstack::Memory; 65using unwindstack::Memory;
66using unwindstack::Regs; 66using unwindstack::Regs;
67 67
68using namespace std::literals::string_literals;
69
68#define STACK_WORDS 16 70#define STACK_WORDS 16
69 71
70static void dump_header_info(log_t* log) { 72static void dump_header_info(log_t* log) {
@@ -148,8 +150,9 @@ static void dump_stack_segment(log_t* log, BacktraceMap* backtrace_map, Memory*
148 150
149 backtrace_map_t map; 151 backtrace_map_t map;
150 backtrace_map->FillIn(stack_data[i], &map); 152 backtrace_map->FillIn(stack_data[i], &map);
151 if (BacktraceMap::IsValid(map) && !map.name.empty()) { 153 std::string map_name{map.Name()};
152 line += " " + map.name; 154 if (BacktraceMap::IsValid(map) && !map_name.empty()) {
155 line += " " + map_name;
153 uint64_t offset = 0; 156 uint64_t offset = 0;
154 std::string func_name = backtrace_map->GetFunctionName(stack_data[i], &offset); 157 std::string func_name = backtrace_map->GetFunctionName(stack_data[i], &offset);
155 if (!func_name.empty()) { 158 if (!func_name.empty()) {
@@ -382,9 +385,16 @@ void dump_registers(log_t* log, Regs* regs) {
382 print_register_row(log, special_row); 385 print_register_row(log, special_row);
383} 386}
384 387
385void dump_memory_and_code(log_t* log, Memory* memory, Regs* regs) { 388void dump_memory_and_code(log_t* log, BacktraceMap* map, Memory* memory, Regs* regs) {
386 regs->IterateRegisters([log, memory](const char* name, uint64_t value) { 389 regs->IterateRegisters([log, map, memory](const char* reg_name, uint64_t reg_value) {
387 dump_memory(log, memory, value, "memory near %s:", name); 390 std::string label{"memory near "s + reg_name};
391 if (map) {
392 backtrace_map_t map_info;
393 map->FillIn(reg_value, &map_info);
394 std::string map_name{map_info.Name()};
395 if (!map_name.empty()) label += " (" + map_info.Name() + ")";
396 }
397 dump_memory(log, memory, reg_value, label);
388 }); 398 });
389} 399}
390 400
@@ -423,7 +433,7 @@ static bool dump_thread(log_t* log, BacktraceMap* map, Memory* process_memory,
423 } 433 }
424 434
425 if (primary_thread) { 435 if (primary_thread) {
426 dump_memory_and_code(log, process_memory, thread_info.registers.get()); 436 dump_memory_and_code(log, map, process_memory, thread_info.registers.get());
427 if (map) { 437 if (map) {
428 uint64_t addr = 0; 438 uint64_t addr = 0;
429 siginfo_t* si = thread_info.siginfo; 439 siginfo_t* si = thread_info.siginfo;
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 3ac98f58f..d1538653d 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -124,13 +124,7 @@ void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) {
124#define MEMORY_BYTES_TO_DUMP 256 124#define MEMORY_BYTES_TO_DUMP 256
125#define MEMORY_BYTES_PER_LINE 16 125#define MEMORY_BYTES_PER_LINE 16
126 126
127void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const char* fmt, ...) { 127void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const std::string& label) {
128 std::string log_msg;
129 va_list ap;
130 va_start(ap, fmt);
131 android::base::StringAppendV(&log_msg, fmt, ap);
132 va_end(ap);
133
134 // Align the address to sizeof(long) and start 32 bytes before the address. 128 // Align the address to sizeof(long) and start 32 bytes before the address.
135 addr &= ~(sizeof(long) - 1); 129 addr &= ~(sizeof(long) - 1);
136 if (addr >= 4128) { 130 if (addr >= 4128) {
@@ -147,7 +141,7 @@ void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const c
147 return; 141 return;
148 } 142 }
149 143
150 _LOG(log, logtype::MEMORY, "\n%s\n", log_msg.c_str()); 144 _LOG(log, logtype::MEMORY, "\n%s:\n", label.c_str());
151 145
152 // Dump 256 bytes 146 // Dump 256 bytes
153 uintptr_t data[MEMORY_BYTES_TO_DUMP/sizeof(uintptr_t)]; 147 uintptr_t data[MEMORY_BYTES_TO_DUMP/sizeof(uintptr_t)];
diff --git a/debuggerd/seccomp_policy/crash_dump.arm.policy b/debuggerd/seccomp_policy/crash_dump.arm.policy
index b1f459da8..254330d51 100644
--- a/debuggerd/seccomp_policy/crash_dump.arm.policy
+++ b/debuggerd/seccomp_policy/crash_dump.arm.policy
@@ -26,11 +26,11 @@ rt_sigaction: 1
26rt_tgsigqueueinfo: 1 26rt_tgsigqueueinfo: 1
27prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 27prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
28madvise: 1 28madvise: 1
29mprotect: arg2 in PROT_READ|PROT_WRITE 29mprotect: arg2 in 0x1|0x2
30munmap: 1 30munmap: 1
31getuid32: 1 31getuid32: 1
32fstat64: 1 32fstat64: 1
33mmap2: arg2 in PROT_READ|PROT_WRITE 33mmap2: arg2 in 0x1|0x2
34geteuid32: 1 34geteuid32: 1
35getgid32: 1 35getgid32: 1
36getegid32: 1 36getegid32: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.arm64.policy b/debuggerd/seccomp_policy/crash_dump.arm64.policy
index e5e7afb2c..9b3ef09ef 100644
--- a/debuggerd/seccomp_policy/crash_dump.arm64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.arm64.policy
@@ -25,11 +25,11 @@ rt_sigaction: 1
25rt_tgsigqueueinfo: 1 25rt_tgsigqueueinfo: 1
26prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 26prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
27madvise: 1 27madvise: 1
28mprotect: arg2 in PROT_READ|PROT_WRITE 28mprotect: arg2 in 0x1|0x2
29munmap: 1 29munmap: 1
30getuid: 1 30getuid: 1
31fstat: 1 31fstat: 1
32mmap: arg2 in PROT_READ|PROT_WRITE 32mmap: arg2 in 0x1|0x2
33geteuid: 1 33geteuid: 1
34getgid: 1 34getgid: 1
35getegid: 1 35getegid: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.policy.def b/debuggerd/seccomp_policy/crash_dump.policy.def
index b78c94a2b..2ef31b0b0 100644
--- a/debuggerd/seccomp_policy/crash_dump.policy.def
+++ b/debuggerd/seccomp_policy/crash_dump.policy.def
@@ -35,6 +35,14 @@ rt_tgsigqueueinfo: 1
35#define PR_SET_VMA 0x53564d41 35#define PR_SET_VMA 0x53564d41
36prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == PR_SET_VMA 36prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == PR_SET_VMA
37 37
38#if 0
39libminijail on vendor partitions older than P does not have constants from <sys/mman.h>.
40Define the values of PROT_READ and PROT_WRITE ourselves to maintain backwards compatibility.
41#else
42#define PROT_READ 0x1
43#define PROT_WRITE 0x2
44#endif
45
38madvise: 1 46madvise: 1
39mprotect: arg2 in PROT_READ|PROT_WRITE 47mprotect: arg2 in PROT_READ|PROT_WRITE
40munmap: 1 48munmap: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.x86.policy b/debuggerd/seccomp_policy/crash_dump.x86.policy
index b1f459da8..254330d51 100644
--- a/debuggerd/seccomp_policy/crash_dump.x86.policy
+++ b/debuggerd/seccomp_policy/crash_dump.x86.policy
@@ -26,11 +26,11 @@ rt_sigaction: 1
26rt_tgsigqueueinfo: 1 26rt_tgsigqueueinfo: 1
27prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 27prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
28madvise: 1 28madvise: 1
29mprotect: arg2 in PROT_READ|PROT_WRITE 29mprotect: arg2 in 0x1|0x2
30munmap: 1 30munmap: 1
31getuid32: 1 31getuid32: 1
32fstat64: 1 32fstat64: 1
33mmap2: arg2 in PROT_READ|PROT_WRITE 33mmap2: arg2 in 0x1|0x2
34geteuid32: 1 34geteuid32: 1
35getgid32: 1 35getgid32: 1
36getegid32: 1 36getegid32: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.x86_64.policy b/debuggerd/seccomp_policy/crash_dump.x86_64.policy
index e5e7afb2c..9b3ef09ef 100644
--- a/debuggerd/seccomp_policy/crash_dump.x86_64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.x86_64.policy
@@ -25,11 +25,11 @@ rt_sigaction: 1
25rt_tgsigqueueinfo: 1 25rt_tgsigqueueinfo: 1
26prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41 26prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
27madvise: 1 27madvise: 1
28mprotect: arg2 in PROT_READ|PROT_WRITE 28mprotect: arg2 in 0x1|0x2
29munmap: 1 29munmap: 1
30getuid: 1 30getuid: 1
31fstat: 1 31fstat: 1
32mmap: arg2 in PROT_READ|PROT_WRITE 32mmap: arg2 in 0x1|0x2
33geteuid: 1 33geteuid: 1
34getgid: 1 34getgid: 1
35getegid: 1 35getegid: 1
diff --git a/demangle/Android.bp b/demangle/Android.bp
index 89b87725f..8d5b1350c 100644
--- a/demangle/Android.bp
+++ b/demangle/Android.bp
@@ -42,11 +42,11 @@ cc_library {
42 ], 42 ],
43 43
44 local_include_dirs: [ 44 local_include_dirs: [
45 "include", 45 "include",
46 ], 46 ],
47 47
48 export_include_dirs: [ 48 export_include_dirs: [
49 "include", 49 "include",
50 ], 50 ],
51} 51}
52 52
diff --git a/diagnose_usb/Android.bp b/diagnose_usb/Android.bp
new file mode 100644
index 000000000..a7ecf3737
--- /dev/null
+++ b/diagnose_usb/Android.bp
@@ -0,0 +1,13 @@
1cc_library_static {
2 name: "libdiagnose_usb",
3 cflags: ["-Wall", "-Wextra", "-Werror"],
4 host_supported: true,
5 target: {
6 windows: {
7 enabled: true,
8 },
9 },
10 srcs: ["diagnose_usb.cpp"],
11 export_include_dirs: ["include"],
12 static_libs: ["libbase"],
13}
diff --git a/diagnose_usb/OWNERS b/diagnose_usb/OWNERS
new file mode 100644
index 000000000..643b4489f
--- /dev/null
+++ b/diagnose_usb/OWNERS
@@ -0,0 +1,2 @@
1jmgao@google.com
2yabinc@google.com
diff --git a/adb/diagnose_usb.cpp b/diagnose_usb/diagnose_usb.cpp
index 9f721bf5f..5695ecec5 100644
--- a/adb/diagnose_usb.cpp
+++ b/diagnose_usb/diagnose_usb.cpp
@@ -33,7 +33,7 @@ static const char kPermissionsHelpUrl[] = "http://developer.android.com/tools/de
33// Returns a message describing any potential problems we find with udev, or an empty string if we 33// Returns a message describing any potential problems we find with udev, or an empty string if we
34// can't find plugdev information (i.e. udev is not installed). 34// can't find plugdev information (i.e. udev is not installed).
35static std::string GetUdevProblem() { 35static std::string GetUdevProblem() {
36#if defined(__linux__) 36#if defined(__linux__) && !defined(__BIONIC__)
37 errno = 0; 37 errno = 0;
38 group* plugdev_group = getgrnam("plugdev"); 38 group* plugdev_group = getgrnam("plugdev");
39 39
diff --git a/adb/diagnose_usb.h b/diagnose_usb/include/diagnose_usb.h
index 325b2e3b6..325b2e3b6 100644
--- a/adb/diagnose_usb.h
+++ b/diagnose_usb/include/diagnose_usb.h
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index dfcf090b7..f5bcc264d 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -39,13 +39,15 @@ LOCAL_MODULE := fastboot
39LOCAL_MODULE_TAGS := debug 39LOCAL_MODULE_TAGS := debug
40LOCAL_MODULE_HOST_OS := darwin linux windows 40LOCAL_MODULE_HOST_OS := darwin linux windows
41LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code 41LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
42LOCAL_REQUIRED_MODULES := mke2fs e2fsdroid mke2fs.conf make_f2fs sload_f2fs 42LOCAL_REQUIRED_MODULES := mke2fs make_f2fs
43 43
44LOCAL_SRC_FILES_linux := usb_linux.cpp 44LOCAL_SRC_FILES_linux := usb_linux.cpp
45LOCAL_STATIC_LIBRARIES_linux := libselinux 45LOCAL_STATIC_LIBRARIES_linux := libselinux
46LOCAL_REQUIRED_MODULES_linux := e2fsdroid mke2fs.conf sload_f2fs
46 47
47LOCAL_SRC_FILES_darwin := usb_osx.cpp 48LOCAL_SRC_FILES_darwin := usb_osx.cpp
48LOCAL_STATIC_LIBRARIES_darwin := libselinux 49LOCAL_STATIC_LIBRARIES_darwin := libselinux
50LOCAL_REQUIRED_MODULES_darwin := e2fsdroid mke2fs.conf sload_f2fs
49LOCAL_LDLIBS_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon 51LOCAL_LDLIBS_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
50LOCAL_CFLAGS_darwin := -Wno-unused-parameter 52LOCAL_CFLAGS_darwin := -Wno-unused-parameter
51 53
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 1c01d8c87..9b7405a3d 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -39,6 +39,7 @@ struct fs_mgr_flag_values {
39 char *key_loc; 39 char *key_loc;
40 char* key_dir; 40 char* key_dir;
41 char *verity_loc; 41 char *verity_loc;
42 char *sysfs_path;
42 long long part_length; 43 long long part_length;
43 char *label; 44 char *label;
44 int partnum; 45 int partnum;
@@ -104,6 +105,7 @@ static struct flag_list fs_mgr_flags[] = {
104 {"quota", MF_QUOTA}, 105 {"quota", MF_QUOTA},
105 {"eraseblk=", MF_ERASEBLKSIZE}, 106 {"eraseblk=", MF_ERASEBLKSIZE},
106 {"logicalblk=", MF_LOGICALBLKSIZE}, 107 {"logicalblk=", MF_LOGICALBLKSIZE},
108 {"sysfs_path=", MF_SYSFS},
107 {"defaults", 0}, 109 {"defaults", 0},
108 {0, 0}, 110 {0, 0},
109}; 111};
@@ -341,6 +343,9 @@ static int parse_flags(char *flags, struct flag_list *fl,
341 unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0); 343 unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
342 if (val >= 4096 && (val & (val - 1)) == 0) 344 if (val >= 4096 && (val & (val - 1)) == 0)
343 flag_vals->logical_blk_size = val; 345 flag_vals->logical_blk_size = val;
346 } else if ((fl[i].flag == MF_SYSFS) && flag_vals) {
347 /* The path to trigger device gc by idle-maint of vold. */
348 flag_vals->sysfs_path = strdup(strchr(p, '=') + 1);
344 } 349 }
345 break; 350 break;
346 } 351 }
@@ -615,6 +620,7 @@ static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
615 fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode; 620 fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode;
616 fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size; 621 fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
617 fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size; 622 fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
623 fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path;
618 cnt++; 624 cnt++;
619 } 625 }
620 /* If an A/B partition, modify block device to be the real block device */ 626 /* If an A/B partition, modify block device to be the real block device */
@@ -787,6 +793,7 @@ void fs_mgr_free_fstab(struct fstab *fstab)
787 free(fstab->recs[i].key_loc); 793 free(fstab->recs[i].key_loc);
788 free(fstab->recs[i].key_dir); 794 free(fstab->recs[i].key_dir);
789 free(fstab->recs[i].label); 795 free(fstab->recs[i].label);
796 free(fstab->recs[i].sysfs_path);
790 } 797 }
791 798
792 /* Free the fstab_recs array created by calloc(3) */ 799 /* Free the fstab_recs array created by calloc(3) */
@@ -922,3 +929,8 @@ int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
922int fs_mgr_is_quota(const struct fstab_rec* fstab) { 929int fs_mgr_is_quota(const struct fstab_rec* fstab) {
923 return fstab->fs_mgr_flags & MF_QUOTA; 930 return fstab->fs_mgr_flags & MF_QUOTA;
924} 931}
932
933int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab)
934{
935 return fstab->fs_mgr_flags & MF_SYSFS;
936}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 724156d70..ade0cc4cd 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -109,7 +109,8 @@
109#define MF_ERASEBLKSIZE 0x800000 109#define MF_ERASEBLKSIZE 0x800000
110#define MF_LOGICALBLKSIZE 0X1000000 110#define MF_LOGICALBLKSIZE 0X1000000
111#define MF_AVB 0X2000000 111#define MF_AVB 0X2000000
112#define MF_KEYDIRECTORY 0X4000000 112#define MF_KEYDIRECTORY 0X4000000
113#define MF_SYSFS 0X8000000
113 114
114#define DM_BUF_SIZE 4096 115#define DM_BUF_SIZE 4096
115 116
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 94aacfdb3..8c585dd2f 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -56,6 +56,7 @@ struct fstab_rec {
56 unsigned int file_names_mode; 56 unsigned int file_names_mode;
57 unsigned int erase_blk_size; 57 unsigned int erase_blk_size;
58 unsigned int logical_blk_size; 58 unsigned int logical_blk_size;
59 char* sysfs_path;
59}; 60};
60 61
61struct fstab* fs_mgr_read_fstab_default(); 62struct fstab* fs_mgr_read_fstab_default();
@@ -83,6 +84,7 @@ int fs_mgr_is_slotselect(const struct fstab_rec* fstab);
83int fs_mgr_is_nofail(const struct fstab_rec* fstab); 84int fs_mgr_is_nofail(const struct fstab_rec* fstab);
84int fs_mgr_is_latemount(const struct fstab_rec* fstab); 85int fs_mgr_is_latemount(const struct fstab_rec* fstab);
85int fs_mgr_is_quota(const struct fstab_rec* fstab); 86int fs_mgr_is_quota(const struct fstab_rec* fstab);
87int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);
86 88
87std::string fs_mgr_get_slot_suffix(); 89std::string fs_mgr_get_slot_suffix();
88 90
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 08b8b269d..fa79d0bb2 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -143,7 +143,7 @@ int BatteryMonitor::readFromFile(const String8& path, std::string* buf) {
143 143
144BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) { 144BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
145 std::string buf; 145 std::string buf;
146 BatteryMonitor::PowerSupplyType ret; 146 int ret;
147 struct sysfsStringEnumMap supplyTypeMap[] = { 147 struct sysfsStringEnumMap supplyTypeMap[] = {
148 { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN }, 148 { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
149 { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY }, 149 { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
@@ -164,13 +164,13 @@ BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String
164 if (readFromFile(path, &buf) <= 0) 164 if (readFromFile(path, &buf) <= 0)
165 return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN; 165 return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
166 166
167 ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf.c_str(), supplyTypeMap); 167 ret = mapSysfsString(buf.c_str(), supplyTypeMap);
168 if (ret < 0) { 168 if (ret < 0) {
169 KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str()); 169 KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
170 ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN; 170 ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
171 } 171 }
172 172
173 return ret; 173 return static_cast<BatteryMonitor::PowerSupplyType>(ret);
174} 174}
175 175
176bool BatteryMonitor::getBooleanField(const String8& path) { 176bool BatteryMonitor::getBooleanField(const String8& path) {
diff --git a/init/Android.bp b/init/Android.bp
index 6c80ee6cf..31c8efb09 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -56,7 +56,7 @@ cc_defaults {
56 }, 56 },
57 uml: { 57 uml: {
58 cppflags: ["-DUSER_MODE_LINUX"], 58 cppflags: ["-DUSER_MODE_LINUX"],
59 } 59 },
60 }, 60 },
61 static_libs: [ 61 static_libs: [
62 "libbootloader_message", 62 "libbootloader_message",
@@ -93,6 +93,8 @@ cc_library_static {
93 defaults: ["init_defaults"], 93 defaults: ["init_defaults"],
94 srcs: [ 94 srcs: [
95 "action.cpp", 95 "action.cpp",
96 "action_manager.cpp",
97 "action_parser.cpp",
96 "bootchart.cpp", 98 "bootchart.cpp",
97 "builtins.cpp", 99 "builtins.cpp",
98 "capabilities.cpp", 100 "capabilities.cpp",
@@ -192,4 +194,67 @@ cc_benchmark {
192 static_libs: ["libinit"], 194 static_libs: ["libinit"],
193} 195}
194 196
197// Host Verifier
198// ------------------------------------------------------------------------------
199
200genrule {
201 name: "generated_stub_builtin_function_map",
202 out: ["generated_stub_builtin_function_map.h"],
203 srcs: ["builtins.cpp"],
204 cmd: "sed -n '/Builtin-function-map start/{:a;n;/Builtin-function-map end/q;p;ba}' $(in) | sed -e 's/do_[^}]*/do_stub/g' > $(out)",
205}
206
207cc_binary {
208 name: "host_init_verifier",
209 host_supported: true,
210 cpp_std: "experimental",
211 cflags: [
212 "-Wall",
213 "-Wextra",
214 "-Wno-unused-parameter",
215 "-Werror",
216 ],
217 static_libs: [
218 "libbase",
219 "libselinux",
220 ],
221 whole_static_libs: ["libcap"],
222 shared_libs: [
223 "libprotobuf-cpp-lite",
224 "libhidl-gen-utils",
225 "libprocessgroup",
226 "liblog",
227 "libcutils",
228 ],
229 srcs: [
230 "action.cpp",
231 "action_manager.cpp",
232 "action_parser.cpp",
233 "capabilities.cpp",
234 "descriptors.cpp",
235 "import_parser.cpp",
236 "host_init_parser.cpp",
237 "host_init_stubs.cpp",
238 "parser.cpp",
239 "rlimit_parser.cpp",
240 "tokenizer.cpp",
241 "service.cpp",
242 "subcontext.cpp",
243 "subcontext.proto",
244 "util.cpp",
245 ],
246 proto: {
247 type: "lite",
248 },
249 generated_headers: ["generated_stub_builtin_function_map"],
250 target: {
251 android: {
252 enabled: false,
253 },
254 darwin: {
255 enabled: false,
256 },
257 },
258}
259
195subdirs = ["*"] 260subdirs = ["*"]
diff --git a/init/README.md b/init/README.md
index d7edf21ac..5c2352b9f 100644
--- a/init/README.md
+++ b/init/README.md
@@ -10,7 +10,11 @@ whitespace into a token. Double quotes may also be used to prevent
10whitespace from breaking text into multiple tokens. The backslash, 10whitespace from breaking text into multiple tokens. The backslash,
11when it is the last character on a line, may be used for line-folding. 11when it is the last character on a line, may be used for line-folding.
12 12
13Lines which start with a # (leading whitespace allowed) are comments. 13Lines which start with a `#` (leading whitespace allowed) are comments.
14
15System properties can be expanded using the syntax
16`${property.name}`. This also works in contexts where concatenation is
17required, such as `import /init.recovery.${ro.hardware}.rc`.
14 18
15Actions and Services implicitly declare a new section. All commands 19Actions and Services implicitly declare a new section. All commands
16or options belong to the section most recently declared. Commands 20or options belong to the section most recently declared. Commands
diff --git a/init/action.cpp b/init/action.cpp
index ba03e66fe..f782b51c1 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -18,14 +18,17 @@
18 18
19#include <android-base/chrono_utils.h> 19#include <android-base/chrono_utils.h>
20#include <android-base/logging.h> 20#include <android-base/logging.h>
21#include <android-base/properties.h>
22#include <android-base/strings.h> 21#include <android-base/strings.h>
23 22
24#include "stable_properties.h"
25#include "util.h" 23#include "util.h"
26 24
25#if defined(__ANDROID__)
26#include <android-base/properties.h>
27#else
28#include "host_init_stubs.h"
29#endif
30
27using android::base::Join; 31using android::base::Join;
28using android::base::StartsWith;
29 32
30namespace android { 33namespace android {
31namespace init { 34namespace init {
@@ -70,8 +73,15 @@ std::string Command::BuildCommandString() const {
70 return Join(args_, ' '); 73 return Join(args_, ' ');
71} 74}
72 75
73Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line) 76Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line,
74 : oneshot_(oneshot), subcontext_(subcontext), filename_(filename), line_(line) {} 77 const std::string& event_trigger,
78 const std::map<std::string, std::string>& property_triggers)
79 : property_triggers_(property_triggers),
80 event_trigger_(event_trigger),
81 oneshot_(oneshot),
82 subcontext_(subcontext),
83 filename_(filename),
84 line_(line) {}
75 85
76const KeywordFunctionMap* Action::function_map_ = nullptr; 86const KeywordFunctionMap* Action::function_map_ = nullptr;
77 87
@@ -135,85 +145,6 @@ void Action::ExecuteCommand(const Command& command) const {
135 } 145 }
136} 146}
137 147
138static bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) {
139 static bool enabled =
140 android::base::GetBoolProperty("ro.actionable_compatible_property.enabled", false);
141
142 if (subcontext == nullptr || !enabled) {
143 return true;
144 }
145
146 if (kExportedActionableProperties.count(prop_name) == 1) {
147 return true;
148 }
149 for (const auto& prefix : kPartnerPrefixes) {
150 if (android::base::StartsWith(prop_name, prefix)) {
151 return true;
152 }
153 }
154 return false;
155}
156
157Result<Success> Action::ParsePropertyTrigger(const std::string& trigger) {
158 const static std::string prop_str("property:");
159 std::string prop_name(trigger.substr(prop_str.length()));
160 size_t equal_pos = prop_name.find('=');
161 if (equal_pos == std::string::npos) {
162 return Error() << "property trigger found without matching '='";
163 }
164
165 std::string prop_value(prop_name.substr(equal_pos + 1));
166 prop_name.erase(equal_pos);
167
168 if (!IsActionableProperty(subcontext_, prop_name)) {
169 return Error() << "unexported property tigger found: " << prop_name;
170 }
171
172 if (auto [it, inserted] = property_triggers_.emplace(prop_name, prop_value); !inserted) {
173 return Error() << "multiple property triggers found for same property";
174 }
175 return Success();
176}
177
178Result<Success> Action::InitTriggers(const std::vector<std::string>& args) {
179 const static std::string prop_str("property:");
180 for (std::size_t i = 0; i < args.size(); ++i) {
181 if (args[i].empty()) {
182 return Error() << "empty trigger is not valid";
183 }
184
185 if (i % 2) {
186 if (args[i] != "&&") {
187 return Error() << "&& is the only symbol allowed to concatenate actions";
188 } else {
189 continue;
190 }
191 }
192
193 if (!args[i].compare(0, prop_str.length(), prop_str)) {
194 if (auto result = ParsePropertyTrigger(args[i]); !result) {
195 return result;
196 }
197 } else {
198 if (!event_trigger_.empty()) {
199 return Error() << "multiple event triggers are not allowed";
200 }
201
202 event_trigger_ = args[i];
203 }
204 }
205
206 return Success();
207}
208
209Result<Success> Action::InitSingleTrigger(const std::string& trigger) {
210 std::vector<std::string> name_vector{trigger};
211 if (auto result = InitTriggers(name_vector); !result) {
212 return Error() << "InitTriggers() failed: " << result.error();
213 }
214 return Success();
215}
216
217// This function checks that all property triggers are satisfied, that is 148// This function checks that all property triggers are satisfied, that is
218// for each (name, value) in property_triggers_, check that the current 149// for each (name, value) in property_triggers_, check that the current
219// value of the property 'name' == value. 150// value of the property 'name' == value.
@@ -281,142 +212,5 @@ void Action::DumpState() const {
281 } 212 }
282} 213}
283 214
284ActionManager::ActionManager() : current_command_(0) {
285}
286
287ActionManager& ActionManager::GetInstance() {
288 static ActionManager instance;
289 return instance;
290}
291
292void ActionManager::AddAction(std::unique_ptr<Action> action) {
293 actions_.emplace_back(std::move(action));
294}
295
296void ActionManager::QueueEventTrigger(const std::string& trigger) {
297 event_queue_.emplace(trigger);
298}
299
300void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
301 event_queue_.emplace(std::make_pair(name, value));
302}
303
304void ActionManager::QueueAllPropertyActions() {
305 QueuePropertyChange("", "");
306}
307
308void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
309 auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0);
310 std::vector<std::string> name_vector{name};
311
312 if (auto result = action->InitSingleTrigger(name); !result) {
313 LOG(ERROR) << "Cannot queue BuiltinAction for " << name << ": " << result.error();
314 return;
315 }
316
317 action->AddCommand(func, name_vector, 0);
318
319 event_queue_.emplace(action.get());
320 actions_.emplace_back(std::move(action));
321}
322
323void ActionManager::ExecuteOneCommand() {
324 // Loop through the event queue until we have an action to execute
325 while (current_executing_actions_.empty() && !event_queue_.empty()) {
326 for (const auto& action : actions_) {
327 if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
328 event_queue_.front())) {
329 current_executing_actions_.emplace(action.get());
330 }
331 }
332 event_queue_.pop();
333 }
334
335 if (current_executing_actions_.empty()) {
336 return;
337 }
338
339 auto action = current_executing_actions_.front();
340
341 if (current_command_ == 0) {
342 std::string trigger_name = action->BuildTriggersString();
343 LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
344 << ":" << action->line() << ")";
345 }
346
347 action->ExecuteOneCommand(current_command_);
348
349 // If this was the last command in the current action, then remove
350 // the action from the executing list.
351 // If this action was oneshot, then also remove it from actions_.
352 ++current_command_;
353 if (current_command_ == action->NumCommands()) {
354 current_executing_actions_.pop();
355 current_command_ = 0;
356 if (action->oneshot()) {
357 auto eraser = [&action] (std::unique_ptr<Action>& a) {
358 return a.get() == action;
359 };
360 actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
361 }
362 }
363}
364
365bool ActionManager::HasMoreCommands() const {
366 return !current_executing_actions_.empty() || !event_queue_.empty();
367}
368
369void ActionManager::DumpState() const {
370 for (const auto& a : actions_) {
371 a->DumpState();
372 }
373}
374
375void ActionManager::ClearQueue() {
376 // We are shutting down so don't claim the oneshot builtin actions back
377 current_executing_actions_ = {};
378 event_queue_ = {};
379 current_command_ = 0;
380}
381
382Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args,
383 const std::string& filename, int line) {
384 std::vector<std::string> triggers(args.begin() + 1, args.end());
385 if (triggers.size() < 1) {
386 return Error() << "Actions must have a trigger";
387 }
388
389 Subcontext* action_subcontext = nullptr;
390 if (subcontexts_) {
391 for (auto& subcontext : *subcontexts_) {
392 if (StartsWith(filename, subcontext.path_prefix())) {
393 action_subcontext = &subcontext;
394 break;
395 }
396 }
397 }
398
399 auto action = std::make_unique<Action>(false, action_subcontext, filename, line);
400
401 if (auto result = action->InitTriggers(triggers); !result) {
402 return Error() << "InitTriggers() failed: " << result.error();
403 }
404
405 action_ = std::move(action);
406 return Success();
407}
408
409Result<Success> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
410 return action_ ? action_->AddCommand(std::move(args), line) : Success();
411}
412
413Result<Success> ActionParser::EndSection() {
414 if (action_ && action_->NumCommands() > 0) {
415 action_manager_->AddAction(std::move(action_));
416 }
417
418 return Success();
419}
420
421} // namespace init 215} // namespace init
422} // namespace android 216} // namespace android
diff --git a/init/action.h b/init/action.h
index 1bfc6c753..4f063cc54 100644
--- a/init/action.h
+++ b/init/action.h
@@ -25,7 +25,6 @@
25 25
26#include "builtins.h" 26#include "builtins.h"
27#include "keyword_map.h" 27#include "keyword_map.h"
28#include "parser.h"
29#include "result.h" 28#include "result.h"
30#include "subcontext.h" 29#include "subcontext.h"
31 30
@@ -58,12 +57,12 @@ using BuiltinAction = class Action*;
58 57
59class Action { 58class Action {
60 public: 59 public:
61 Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line); 60 Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line,
61 const std::string& event_trigger,
62 const std::map<std::string, std::string>& property_triggers);
62 63
63 Result<Success> AddCommand(const std::vector<std::string>& args, int line); 64 Result<Success> AddCommand(const std::vector<std::string>& args, int line);
64 void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line); 65 void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line);
65 Result<Success> InitTriggers(const std::vector<std::string>& args);
66 Result<Success> InitSingleTrigger(const std::string& trigger);
67 std::size_t NumCommands() const; 66 std::size_t NumCommands() const;
68 void ExecuteOneCommand(std::size_t command) const; 67 void ExecuteOneCommand(std::size_t command) const;
69 void ExecuteAllCommands() const; 68 void ExecuteAllCommands() const;
@@ -84,7 +83,6 @@ class Action {
84 void ExecuteCommand(const Command& command) const; 83 void ExecuteCommand(const Command& command) const;
85 bool CheckPropertyTriggers(const std::string& name = "", 84 bool CheckPropertyTriggers(const std::string& name = "",
86 const std::string& value = "") const; 85 const std::string& value = "") const;
87 Result<Success> ParsePropertyTrigger(const std::string& trigger);
88 86
89 std::map<std::string, std::string> property_triggers_; 87 std::map<std::string, std::string> property_triggers_;
90 std::string event_trigger_; 88 std::string event_trigger_;
@@ -96,48 +94,6 @@ class Action {
96 static const KeywordFunctionMap* function_map_; 94 static const KeywordFunctionMap* function_map_;
97}; 95};
98 96
99class ActionManager {
100 public:
101 static ActionManager& GetInstance();
102
103 // Exposed for testing
104 ActionManager();
105
106 void AddAction(std::unique_ptr<Action> action);
107 void QueueEventTrigger(const std::string& trigger);
108 void QueuePropertyChange(const std::string& name, const std::string& value);
109 void QueueAllPropertyActions();
110 void QueueBuiltinAction(BuiltinFunction func, const std::string& name);
111 void ExecuteOneCommand();
112 bool HasMoreCommands() const;
113 void DumpState() const;
114 void ClearQueue();
115
116 private:
117 ActionManager(ActionManager const&) = delete;
118 void operator=(ActionManager const&) = delete;
119
120 std::vector<std::unique_ptr<Action>> actions_;
121 std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_;
122 std::queue<const Action*> current_executing_actions_;
123 std::size_t current_command_;
124};
125
126class ActionParser : public SectionParser {
127 public:
128 ActionParser(ActionManager* action_manager, std::vector<Subcontext>* subcontexts)
129 : action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {}
130 Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
131 int line) override;
132 Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
133 Result<Success> EndSection() override;
134
135 private:
136 ActionManager* action_manager_;
137 std::vector<Subcontext>* subcontexts_;
138 std::unique_ptr<Action> action_;
139};
140
141} // namespace init 97} // namespace init
142} // namespace android 98} // namespace android
143 99
diff --git a/init/action_manager.cpp b/init/action_manager.cpp
new file mode 100644
index 000000000..22977bb29
--- /dev/null
+++ b/init/action_manager.cpp
@@ -0,0 +1,116 @@
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "action_manager.h"
18
19#include <android-base/logging.h>
20
21namespace android {
22namespace init {
23
24ActionManager::ActionManager() : current_command_(0) {}
25
26ActionManager& ActionManager::GetInstance() {
27 static ActionManager instance;
28 return instance;
29}
30
31void ActionManager::AddAction(std::unique_ptr<Action> action) {
32 actions_.emplace_back(std::move(action));
33}
34
35void ActionManager::QueueEventTrigger(const std::string& trigger) {
36 event_queue_.emplace(trigger);
37}
38
39void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
40 event_queue_.emplace(std::make_pair(name, value));
41}
42
43void ActionManager::QueueAllPropertyActions() {
44 QueuePropertyChange("", "");
45}
46
47void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
48 auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
49 std::map<std::string, std::string>{});
50 std::vector<std::string> name_vector{name};
51
52 action->AddCommand(func, name_vector, 0);
53
54 event_queue_.emplace(action.get());
55 actions_.emplace_back(std::move(action));
56}
57
58void ActionManager::ExecuteOneCommand() {
59 // Loop through the event queue until we have an action to execute
60 while (current_executing_actions_.empty() && !event_queue_.empty()) {
61 for (const auto& action : actions_) {
62 if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
63 event_queue_.front())) {
64 current_executing_actions_.emplace(action.get());
65 }
66 }
67 event_queue_.pop();
68 }
69
70 if (current_executing_actions_.empty()) {
71 return;
72 }
73
74 auto action = current_executing_actions_.front();
75
76 if (current_command_ == 0) {
77 std::string trigger_name = action->BuildTriggersString();
78 LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
79 << ":" << action->line() << ")";
80 }
81
82 action->ExecuteOneCommand(current_command_);
83
84 // If this was the last command in the current action, then remove
85 // the action from the executing list.
86 // If this action was oneshot, then also remove it from actions_.
87 ++current_command_;
88 if (current_command_ == action->NumCommands()) {
89 current_executing_actions_.pop();
90 current_command_ = 0;
91 if (action->oneshot()) {
92 auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
93 actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
94 }
95 }
96}
97
98bool ActionManager::HasMoreCommands() const {
99 return !current_executing_actions_.empty() || !event_queue_.empty();
100}
101
102void ActionManager::DumpState() const {
103 for (const auto& a : actions_) {
104 a->DumpState();
105 }
106}
107
108void ActionManager::ClearQueue() {
109 // We are shutting down so don't claim the oneshot builtin actions back
110 current_executing_actions_ = {};
111 event_queue_ = {};
112 current_command_ = 0;
113}
114
115} // namespace init
116} // namespace android
diff --git a/init/action_manager.h b/init/action_manager.h
new file mode 100644
index 000000000..5f47a6db0
--- /dev/null
+++ b/init/action_manager.h
@@ -0,0 +1,59 @@
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _INIT_ACTION_MANAGER_H
18#define _INIT_ACTION_MANAGER_H
19
20#include <string>
21#include <vector>
22
23#include "action.h"
24#include "builtins.h"
25
26namespace android {
27namespace init {
28
29class ActionManager {
30 public:
31 static ActionManager& GetInstance();
32
33 // Exposed for testing
34 ActionManager();
35
36 void AddAction(std::unique_ptr<Action> action);
37 void QueueEventTrigger(const std::string& trigger);
38 void QueuePropertyChange(const std::string& name, const std::string& value);
39 void QueueAllPropertyActions();
40 void QueueBuiltinAction(BuiltinFunction func, const std::string& name);
41 void ExecuteOneCommand();
42 bool HasMoreCommands() const;
43 void DumpState() const;
44 void ClearQueue();
45
46 private:
47 ActionManager(ActionManager const&) = delete;
48 void operator=(ActionManager const&) = delete;
49
50 std::vector<std::unique_ptr<Action>> actions_;
51 std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_;
52 std::queue<const Action*> current_executing_actions_;
53 std::size_t current_command_;
54};
55
56} // namespace init
57} // namespace android
58
59#endif
diff --git a/init/action_parser.cpp b/init/action_parser.cpp
new file mode 100644
index 000000000..a2c96718b
--- /dev/null
+++ b/init/action_parser.cpp
@@ -0,0 +1,158 @@
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "action_parser.h"
18
19#include <android-base/strings.h>
20
21#include "stable_properties.h"
22
23#if defined(__ANDROID__)
24#include <android-base/properties.h>
25#else
26#include "host_init_stubs.h"
27#endif
28
29using android::base::GetBoolProperty;
30using android::base::StartsWith;
31
32namespace android {
33namespace init {
34
35namespace {
36
37bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) {
38 static bool enabled = GetBoolProperty("ro.actionable_compatible_property.enabled", false);
39
40 if (subcontext == nullptr || !enabled) {
41 return true;
42 }
43
44 if (kExportedActionableProperties.count(prop_name) == 1) {
45 return true;
46 }
47 for (const auto& prefix : kPartnerPrefixes) {
48 if (android::base::StartsWith(prop_name, prefix)) {
49 return true;
50 }
51 }
52 return false;
53}
54
55Result<Success> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext,
56 std::map<std::string, std::string>* property_triggers) {
57 const static std::string prop_str("property:");
58 std::string prop_name(trigger.substr(prop_str.length()));
59 size_t equal_pos = prop_name.find('=');
60 if (equal_pos == std::string::npos) {
61 return Error() << "property trigger found without matching '='";
62 }
63
64 std::string prop_value(prop_name.substr(equal_pos + 1));
65 prop_name.erase(equal_pos);
66
67 if (!IsActionableProperty(subcontext, prop_name)) {
68 return Error() << "unexported property tigger found: " << prop_name;
69 }
70
71 if (auto [it, inserted] = property_triggers->emplace(prop_name, prop_value); !inserted) {
72 return Error() << "multiple property triggers found for same property";
73 }
74 return Success();
75}
76
77Result<Success> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext,
78 std::string* event_trigger,
79 std::map<std::string, std::string>* property_triggers) {
80 const static std::string prop_str("property:");
81 for (std::size_t i = 0; i < args.size(); ++i) {
82 if (args[i].empty()) {
83 return Error() << "empty trigger is not valid";
84 }
85
86 if (i % 2) {
87 if (args[i] != "&&") {
88 return Error() << "&& is the only symbol allowed to concatenate actions";
89 } else {
90 continue;
91 }
92 }
93
94 if (!args[i].compare(0, prop_str.length(), prop_str)) {
95 if (auto result = ParsePropertyTrigger(args[i], subcontext, property_triggers);
96 !result) {
97 return result;
98 }
99 } else {
100 if (!event_trigger->empty()) {
101 return Error() << "multiple event triggers are not allowed";
102 }
103
104 *event_trigger = args[i];
105 }
106 }
107
108 return Success();
109}
110
111} // namespace
112
113Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args,
114 const std::string& filename, int line) {
115 std::vector<std::string> triggers(args.begin() + 1, args.end());
116 if (triggers.size() < 1) {
117 return Error() << "Actions must have a trigger";
118 }
119
120 Subcontext* action_subcontext = nullptr;
121 if (subcontexts_) {
122 for (auto& subcontext : *subcontexts_) {
123 if (StartsWith(filename, subcontext.path_prefix())) {
124 action_subcontext = &subcontext;
125 break;
126 }
127 }
128 }
129
130 std::string event_trigger;
131 std::map<std::string, std::string> property_triggers;
132
133 if (auto result = ParseTriggers(triggers, action_subcontext, &event_trigger, &property_triggers);
134 !result) {
135 return Error() << "ParseTriggers() failed: " << result.error();
136 }
137
138 auto action = std::make_unique<Action>(false, action_subcontext, filename, line, event_trigger,
139 property_triggers);
140
141 action_ = std::move(action);
142 return Success();
143}
144
145Result<Success> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
146 return action_ ? action_->AddCommand(std::move(args), line) : Success();
147}
148
149Result<Success> ActionParser::EndSection() {
150 if (action_ && action_->NumCommands() > 0) {
151 action_manager_->AddAction(std::move(action_));
152 }
153
154 return Success();
155}
156
157} // namespace init
158} // namespace android
diff --git a/init/action_parser.h b/init/action_parser.h
new file mode 100644
index 000000000..b7f70743a
--- /dev/null
+++ b/init/action_parser.h
@@ -0,0 +1,49 @@
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _INIT_ACTION_PARSER_H
18#define _INIT_ACTION_PARSER_H
19
20#include <string>
21#include <vector>
22
23#include "action.h"
24#include "action_manager.h"
25#include "parser.h"
26#include "subcontext.h"
27
28namespace android {
29namespace init {
30
31class ActionParser : public SectionParser {
32 public:
33 ActionParser(ActionManager* action_manager, std::vector<Subcontext>* subcontexts)
34 : action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {}
35 Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
36 int line) override;
37 Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
38 Result<Success> EndSection() override;
39
40 private:
41 ActionManager* action_manager_;
42 std::vector<Subcontext>* subcontexts_;
43 std::unique_ptr<Action> action_;
44};
45
46} // namespace init
47} // namespace android
48
49#endif
diff --git a/init/builtins.cpp b/init/builtins.cpp
index be259c2e3..fc74dda4b 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -58,7 +58,7 @@
58#include <selinux/selinux.h> 58#include <selinux/selinux.h>
59#include <system/thread_defs.h> 59#include <system/thread_defs.h>
60 60
61#include "action.h" 61#include "action_manager.h"
62#include "bootchart.h" 62#include "bootchart.h"
63#include "init.h" 63#include "init.h"
64#include "parser.h" 64#include "parser.h"
@@ -971,8 +971,8 @@ static Result<Success> do_wait_for_prop(const BuiltinArguments& args) {
971 const char* value = args[2].c_str(); 971 const char* value = args[2].c_str();
972 size_t value_len = strlen(value); 972 size_t value_len = strlen(value);
973 973
974 if (!is_legal_property_name(name)) { 974 if (!IsLegalPropertyName(name)) {
975 return Error() << "is_legal_property_name(" << name << ") failed"; 975 return Error() << "IsLegalPropertyName(" << name << ") failed";
976 } 976 }
977 if (value_len >= PROP_VALUE_MAX) { 977 if (value_len >= PROP_VALUE_MAX) {
978 return Error() << "value too long"; 978 return Error() << "value too long";
@@ -1005,6 +1005,7 @@ static Result<Success> do_init_user0(const BuiltinArguments& args) {
1005 return do_exec({std::move(exec_args), args.context}); 1005 return do_exec({std::move(exec_args), args.context});
1006} 1006}
1007 1007
1008// Builtin-function-map start
1008const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { 1009const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
1009 constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max(); 1010 constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
1010 // clang-format off 1011 // clang-format off
@@ -1062,6 +1063,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
1062 // clang-format on 1063 // clang-format on
1063 return builtin_functions; 1064 return builtin_functions;
1064} 1065}
1066// Builtin-function-map end
1065 1067
1066} // namespace init 1068} // namespace init
1067} // namespace android 1069} // namespace android
diff --git a/init/capabilities.cpp b/init/capabilities.cpp
index 50987db7c..a91cd1dd1 100644
--- a/init/capabilities.cpp
+++ b/init/capabilities.cpp
@@ -14,7 +14,6 @@
14 14
15#include "capabilities.h" 15#include "capabilities.h"
16 16
17#include <sys/capability.h>
18#include <sys/prctl.h> 17#include <sys/prctl.h>
19 18
20#include <map> 19#include <map>
@@ -72,10 +71,15 @@ static const std::map<std::string, int> cap_map = {
72static_assert(CAP_LAST_CAP == CAP_AUDIT_READ, "CAP_LAST_CAP is not CAP_AUDIT_READ"); 71static_assert(CAP_LAST_CAP == CAP_AUDIT_READ, "CAP_LAST_CAP is not CAP_AUDIT_READ");
73 72
74static bool ComputeCapAmbientSupported() { 73static bool ComputeCapAmbientSupported() {
74#if defined(__ANDROID__)
75 return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >= 0; 75 return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >= 0;
76#else
77 return true;
78#endif
76} 79}
77 80
78static unsigned int ComputeLastValidCap() { 81static unsigned int ComputeLastValidCap() {
82#if defined(__ANDROID__)
79 // Android does not support kernels < 3.8. 'CAP_WAKE_ALARM' has been present since 3.0, see 83 // Android does not support kernels < 3.8. 'CAP_WAKE_ALARM' has been present since 3.0, see
80 // http://lxr.free-electrons.com/source/include/linux/capability.h?v=3.0#L360. 84 // http://lxr.free-electrons.com/source/include/linux/capability.h?v=3.0#L360.
81 unsigned int last_valid_cap = CAP_WAKE_ALARM; 85 unsigned int last_valid_cap = CAP_WAKE_ALARM;
@@ -83,6 +87,9 @@ static unsigned int ComputeLastValidCap() {
83 87
84 // |last_valid_cap| will be the first failing value. 88 // |last_valid_cap| will be the first failing value.
85 return last_valid_cap - 1; 89 return last_valid_cap - 1;
90#else
91 return CAP_LAST_CAP;
92#endif
86} 93}
87 94
88static bool DropBoundingSet(const CapSet& to_keep) { 95static bool DropBoundingSet(const CapSet& to_keep) {
@@ -139,6 +146,7 @@ static bool SetProcCaps(const CapSet& to_keep, bool add_setpcap) {
139} 146}
140 147
141static bool SetAmbientCaps(const CapSet& to_raise) { 148static bool SetAmbientCaps(const CapSet& to_raise) {
149#if defined(__ANDROID__)
142 for (size_t cap = 0; cap < to_raise.size(); ++cap) { 150 for (size_t cap = 0; cap < to_raise.size(); ++cap) {
143 if (to_raise.test(cap)) { 151 if (to_raise.test(cap)) {
144 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) != 0) { 152 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) != 0) {
@@ -147,6 +155,7 @@ static bool SetAmbientCaps(const CapSet& to_raise) {
147 } 155 }
148 } 156 }
149 } 157 }
158#endif
150 return true; 159 return true;
151} 160}
152 161
diff --git a/init/capabilities.h b/init/capabilities.h
index fc80c9864..891e0ac98 100644
--- a/init/capabilities.h
+++ b/init/capabilities.h
@@ -21,6 +21,17 @@
21#include <string> 21#include <string>
22#include <type_traits> 22#include <type_traits>
23 23
24#if !defined(__ANDROID__)
25#ifndef CAP_BLOCK_SUSPEND
26#define CAP_BLOCK_SUSPEND 36
27#endif
28#ifndef CAP_AUDIT_READ
29#define CAP_AUDIT_READ 37
30#endif
31#undef CAP_LAST_CAP
32#define CAP_LAST_CAP CAP_AUDIT_READ
33#endif
34
24namespace android { 35namespace android {
25namespace init { 36namespace init {
26 37
diff --git a/init/host_init_parser.cpp b/init/host_init_parser.cpp
new file mode 100644
index 000000000..5232b7e5e
--- /dev/null
+++ b/init/host_init_parser.cpp
@@ -0,0 +1,82 @@
1//
2// Copyright (C) 2018 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include <pwd.h>
18
19#include <android-base/logging.h>
20
21#include "action.h"
22#include "action_manager.h"
23#include "action_parser.h"
24#include "parser.h"
25#include "result.h"
26#include "service.h"
27
28// The host passwd file won't have the Android entries, so we fake success here.
29passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
30 char dummy_buf[] = "dummy";
31 static passwd dummy_passwd = {
32 .pw_name = dummy_buf,
33 .pw_dir = dummy_buf,
34 .pw_shell = dummy_buf,
35 .pw_uid = 123,
36 .pw_gid = 123,
37 };
38 return &dummy_passwd;
39}
40
41namespace android {
42namespace init {
43
44static Result<Success> do_stub(const BuiltinArguments& args) {
45 return Success();
46}
47
48#include "generated_stub_builtin_function_map.h"
49
50int main(int argc, char** argv) {
51 android::base::InitLogging(argv, &android::base::StderrLogger);
52 if (argc != 2) {
53 LOG(ERROR) << "Usage: " << argv[0] << " <init file to parse>";
54 return -1;
55 }
56 const BuiltinFunctionMap function_map;
57 Action::set_function_map(&function_map);
58 ActionManager& am = ActionManager::GetInstance();
59 ServiceList& sl = ServiceList::GetInstance();
60 Parser parser;
61 parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sl, nullptr));
62 parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
63
64 size_t num_errors = 0;
65 if (!parser.ParseConfig(argv[1], &num_errors)) {
66 LOG(ERROR) << "Failed to find script";
67 return -1;
68 }
69 if (num_errors > 0) {
70 LOG(ERROR) << "Parse failed with " << num_errors << " errors";
71 return -1;
72 }
73 LOG(INFO) << "Parse success!";
74 return 0;
75}
76
77} // namespace init
78} // namespace android
79
80int main(int argc, char** argv) {
81 android::init::main(argc, argv);
82}
diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp
new file mode 100644
index 000000000..e6cc08a9a
--- /dev/null
+++ b/init/host_init_stubs.cpp
@@ -0,0 +1,59 @@
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "host_init_stubs.h"
18
19// unistd.h
20int setgroups(size_t __size, const gid_t* __list) {
21 return 0;
22}
23
24namespace android {
25namespace base {
26
27std::string GetProperty(const std::string&, const std::string& default_value) {
28 return default_value;
29}
30
31bool GetBoolProperty(const std::string&, bool default_value) {
32 return default_value;
33}
34
35} // namespace base
36} // namespace android
37
38namespace android {
39namespace init {
40
41// init.h
42std::string default_console = "/dev/console";
43
44// property_service.h
45uint32_t (*property_set)(const std::string& name, const std::string& value) = nullptr;
46uint32_t HandlePropertySet(const std::string&, const std::string&, const std::string&, const ucred&,
47 std::string*) {
48 return 0;
49}
50
51// selinux.h
52void SelabelInitialize() {}
53
54bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
55 return false;
56}
57
58} // namespace init
59} // namespace android
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
new file mode 100644
index 000000000..f31ece60c
--- /dev/null
+++ b/init/host_init_stubs.h
@@ -0,0 +1,60 @@
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _INIT_HOST_INIT_STUBS_H
18#define _INIT_HOST_INIT_STUBS_H
19
20#include <stddef.h>
21#include <sys/socket.h>
22#include <sys/types.h>
23
24#include <string>
25
26// sys/system_properties.h
27#define PROP_VALUE_MAX 92
28
29// unistd.h
30int setgroups(size_t __size, const gid_t* __list);
31
32// android-base/properties.h
33namespace android {
34namespace base {
35
36std::string GetProperty(const std::string& key, const std::string& default_value);
37bool GetBoolProperty(const std::string& key, bool default_value);
38
39} // namespace base
40} // namespace android
41
42namespace android {
43namespace init {
44
45// init.h
46extern std::string default_console;
47
48// property_service.h
49extern uint32_t (*property_set)(const std::string& name, const std::string& value);
50uint32_t HandlePropertySet(const std::string& name, const std::string& value,
51 const std::string& source_context, const ucred& cr, std::string* error);
52
53// selinux.h
54void SelabelInitialize();
55bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
56
57} // namespace init
58} // namespace android
59
60#endif
diff --git a/init/init.cpp b/init/init.cpp
index bd09e4bcc..efb9c1db3 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -35,6 +35,7 @@
35#include <android-base/file.h> 35#include <android-base/file.h>
36#include <android-base/logging.h> 36#include <android-base/logging.h>
37#include <android-base/properties.h> 37#include <android-base/properties.h>
38#include <android-base/stringprintf.h>
38#include <android-base/strings.h> 39#include <android-base/strings.h>
39#include <cutils/android_reboot.h> 40#include <cutils/android_reboot.h>
40#include <keyutils.h> 41#include <keyutils.h>
@@ -45,6 +46,7 @@
45#include <memory> 46#include <memory>
46#include <optional> 47#include <optional>
47 48
49#include "action_parser.h"
48#include "import_parser.h" 50#include "import_parser.h"
49#include "init_first_stage.h" 51#include "init_first_stage.h"
50#include "keychords.h" 52#include "keychords.h"
@@ -62,7 +64,10 @@ using namespace std::string_literals;
62 64
63using android::base::boot_clock; 65using android::base::boot_clock;
64using android::base::GetProperty; 66using android::base::GetProperty;
67using android::base::ReadFileToString;
68using android::base::StringPrintf;
65using android::base::Timer; 69using android::base::Timer;
70using android::base::Trim;
66 71
67namespace android { 72namespace android {
68namespace init { 73namespace init {
@@ -245,7 +250,7 @@ static const std::map<std::string, ControlMessageFunction>& get_control_message_
245 return control_message_functions; 250 return control_message_functions;
246} 251}
247 252
248void handle_control_message(const std::string& msg, const std::string& name) { 253void HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
249 const auto& map = get_control_message_map(); 254 const auto& map = get_control_message_map();
250 const auto it = map.find(msg); 255 const auto it = map.find(msg);
251 256
@@ -254,6 +259,18 @@ void handle_control_message(const std::string& msg, const std::string& name) {
254 return; 259 return;
255 } 260 }
256 261
262 std::string cmdline_path = StringPrintf("proc/%d/cmdline", pid);
263 std::string process_cmdline;
264 if (ReadFileToString(cmdline_path, &process_cmdline)) {
265 std::replace(process_cmdline.begin(), process_cmdline.end(), '\0', ' ');
266 process_cmdline = Trim(process_cmdline);
267 } else {
268 process_cmdline = "unknown process";
269 }
270
271 LOG(INFO) << "Received control message '" << msg << "' for '" << name << "' from pid: " << pid
272 << " (" << process_cmdline << ")";
273
257 const ControlMessageFunction& function = it->second; 274 const ControlMessageFunction& function = it->second;
258 275
259 if (function.target == ControlTarget::SERVICE) { 276 if (function.target == ControlTarget::SERVICE) {
diff --git a/init/init.h b/init/init.h
index ff7bdeb95..d4a0e963b 100644
--- a/init/init.h
+++ b/init/init.h
@@ -17,10 +17,13 @@
17#ifndef _INIT_INIT_H 17#ifndef _INIT_INIT_H
18#define _INIT_INIT_H 18#define _INIT_INIT_H
19 19
20#include <sys/types.h>
21
20#include <string> 22#include <string>
21#include <vector> 23#include <vector>
22 24
23#include "action.h" 25#include "action.h"
26#include "action_manager.h"
24#include "parser.h" 27#include "parser.h"
25#include "service.h" 28#include "service.h"
26 29
@@ -35,7 +38,7 @@ extern std::vector<std::string> late_import_paths;
35 38
36Parser CreateParser(ActionManager& action_manager, ServiceList& service_list); 39Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
37 40
38void handle_control_message(const std::string& msg, const std::string& arg); 41void HandleControlMessage(const std::string& msg, const std::string& arg, pid_t pid);
39 42
40void property_changed(const std::string& name, const std::string& value); 43void property_changed(const std::string& name, const std::string& value);
41 44
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 268873c12..0f9635f81 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -21,6 +21,8 @@
21#include <gtest/gtest.h> 21#include <gtest/gtest.h>
22 22
23#include "action.h" 23#include "action.h"
24#include "action_manager.h"
25#include "action_parser.h"
24#include "builtins.h" 26#include "builtins.h"
25#include "import_parser.h" 27#include "import_parser.h"
26#include "keyword_map.h" 28#include "keyword_map.h"
diff --git a/init/parser.cpp b/init/parser.cpp
index 4c69bac3f..4453aaac1 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -39,7 +39,7 @@ void Parser::AddSingleLineParser(const std::string& prefix, LineCallback callbac
39 line_callbacks_.emplace_back(prefix, callback); 39 line_callbacks_.emplace_back(prefix, callback);
40} 40}
41 41
42void Parser::ParseData(const std::string& filename, const std::string& data) { 42void Parser::ParseData(const std::string& filename, const std::string& data, size_t* parse_errors) {
43 // TODO: Use a parser with const input and remove this copy 43 // TODO: Use a parser with const input and remove this copy
44 std::vector<char> data_copy(data.begin(), data.end()); 44 std::vector<char> data_copy(data.begin(), data.end());
45 data_copy.push_back('\0'); 45 data_copy.push_back('\0');
@@ -57,6 +57,7 @@ void Parser::ParseData(const std::string& filename, const std::string& data) {
57 if (section_parser == nullptr) return; 57 if (section_parser == nullptr) return;
58 58
59 if (auto result = section_parser->EndSection(); !result) { 59 if (auto result = section_parser->EndSection(); !result) {
60 (*parse_errors)++;
60 LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error(); 61 LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error();
61 } 62 }
62 63
@@ -80,6 +81,7 @@ void Parser::ParseData(const std::string& filename, const std::string& data) {
80 end_section(); 81 end_section();
81 82
82 if (auto result = callback(std::move(args)); !result) { 83 if (auto result = callback(std::move(args)); !result) {
84 (*parse_errors)++;
83 LOG(ERROR) << filename << ": " << state.line << ": " << result.error(); 85 LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
84 } 86 }
85 break; 87 break;
@@ -92,12 +94,14 @@ void Parser::ParseData(const std::string& filename, const std::string& data) {
92 if (auto result = 94 if (auto result =
93 section_parser->ParseSection(std::move(args), filename, state.line); 95 section_parser->ParseSection(std::move(args), filename, state.line);
94 !result) { 96 !result) {
97 (*parse_errors)++;
95 LOG(ERROR) << filename << ": " << state.line << ": " << result.error(); 98 LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
96 section_parser = nullptr; 99 section_parser = nullptr;
97 } 100 }
98 } else if (section_parser) { 101 } else if (section_parser) {
99 if (auto result = section_parser->ParseLineSection(std::move(args), state.line); 102 if (auto result = section_parser->ParseLineSection(std::move(args), state.line);
100 !result) { 103 !result) {
104 (*parse_errors)++;
101 LOG(ERROR) << filename << ": " << state.line << ": " << result.error(); 105 LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
102 } 106 }
103 } 107 }
@@ -110,7 +114,7 @@ void Parser::ParseData(const std::string& filename, const std::string& data) {
110 } 114 }
111} 115}
112 116
113bool Parser::ParseConfigFile(const std::string& path) { 117bool Parser::ParseConfigFile(const std::string& path, size_t* parse_errors) {
114 LOG(INFO) << "Parsing file " << path << "..."; 118 LOG(INFO) << "Parsing file " << path << "...";
115 android::base::Timer t; 119 android::base::Timer t;
116 auto config_contents = ReadFile(path); 120 auto config_contents = ReadFile(path);
@@ -120,7 +124,7 @@ bool Parser::ParseConfigFile(const std::string& path) {
120 } 124 }
121 125
122 config_contents->push_back('\n'); // TODO: fix parse_config. 126 config_contents->push_back('\n'); // TODO: fix parse_config.
123 ParseData(path, *config_contents); 127 ParseData(path, *config_contents, parse_errors);
124 for (const auto& [section_name, section_parser] : section_parsers_) { 128 for (const auto& [section_name, section_parser] : section_parsers_) {
125 section_parser->EndFile(); 129 section_parser->EndFile();
126 } 130 }
@@ -129,7 +133,7 @@ bool Parser::ParseConfigFile(const std::string& path) {
129 return true; 133 return true;
130} 134}
131 135
132bool Parser::ParseConfigDir(const std::string& path) { 136bool Parser::ParseConfigDir(const std::string& path, size_t* parse_errors) {
133 LOG(INFO) << "Parsing directory " << path << "..."; 137 LOG(INFO) << "Parsing directory " << path << "...";
134 std::unique_ptr<DIR, decltype(&closedir)> config_dir(opendir(path.c_str()), closedir); 138 std::unique_ptr<DIR, decltype(&closedir)> config_dir(opendir(path.c_str()), closedir);
135 if (!config_dir) { 139 if (!config_dir) {
@@ -149,7 +153,7 @@ bool Parser::ParseConfigDir(const std::string& path) {
149 // Sort first so we load files in a consistent order (bug 31996208) 153 // Sort first so we load files in a consistent order (bug 31996208)
150 std::sort(files.begin(), files.end()); 154 std::sort(files.begin(), files.end());
151 for (const auto& file : files) { 155 for (const auto& file : files) {
152 if (!ParseConfigFile(file)) { 156 if (!ParseConfigFile(file, parse_errors)) {
153 LOG(ERROR) << "could not import file '" << file << "'"; 157 LOG(ERROR) << "could not import file '" << file << "'";
154 } 158 }
155 } 159 }
@@ -157,10 +161,16 @@ bool Parser::ParseConfigDir(const std::string& path) {
157} 161}
158 162
159bool Parser::ParseConfig(const std::string& path) { 163bool Parser::ParseConfig(const std::string& path) {
164 size_t parse_errors;
165 return ParseConfig(path, &parse_errors);
166}
167
168bool Parser::ParseConfig(const std::string& path, size_t* parse_errors) {
169 *parse_errors = 0;
160 if (is_dir(path.c_str())) { 170 if (is_dir(path.c_str())) {
161 return ParseConfigDir(path); 171 return ParseConfigDir(path, parse_errors);
162 } 172 }
163 return ParseConfigFile(path); 173 return ParseConfigFile(path, parse_errors);
164} 174}
165 175
166} // namespace init 176} // namespace init
diff --git a/init/parser.h b/init/parser.h
index 110a4688a..f6e237f57 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -72,13 +72,14 @@ class Parser {
72 Parser(); 72 Parser();
73 73
74 bool ParseConfig(const std::string& path); 74 bool ParseConfig(const std::string& path);
75 bool ParseConfig(const std::string& path, size_t* parse_errors);
75 void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser); 76 void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser);
76 void AddSingleLineParser(const std::string& prefix, LineCallback callback); 77 void AddSingleLineParser(const std::string& prefix, LineCallback callback);
77 78
78 private: 79 private:
79 void ParseData(const std::string& filename, const std::string& data); 80 void ParseData(const std::string& filename, const std::string& data, size_t* parse_errors);
80 bool ParseConfigFile(const std::string& path); 81 bool ParseConfigFile(const std::string& path, size_t* parse_errors);
81 bool ParseConfigDir(const std::string& path); 82 bool ParseConfigDir(const std::string& path, size_t* parse_errors);
82 83
83 std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_; 84 std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_;
84 std::vector<std::pair<std::string, LineCallback>> line_callbacks_; 85 std::vector<std::pair<std::string, LineCallback>> line_callbacks_;
diff --git a/init/property_service.cpp b/init/property_service.cpp
index ecd5baa1d..95ef35c30 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -59,8 +59,11 @@
59#include "init.h" 59#include "init.h"
60#include "persistent_properties.h" 60#include "persistent_properties.h"
61#include "property_type.h" 61#include "property_type.h"
62#include "subcontext.h"
62#include "util.h" 63#include "util.h"
63 64
65using namespace std::literals;
66
64using android::base::ReadFileToString; 67using android::base::ReadFileToString;
65using android::base::Split; 68using android::base::Split;
66using android::base::StartsWith; 69using android::base::StartsWith;
@@ -117,48 +120,21 @@ static bool CheckMacPerms(const std::string& name, const char* target_context,
117 return has_access; 120 return has_access;
118} 121}
119 122
120bool is_legal_property_name(const std::string& name) { 123static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
121 size_t namelen = name.size();
122
123 if (namelen < 1) return false;
124 if (name[0] == '.') return false;
125 if (name[namelen - 1] == '.') return false;
126
127 /* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */
128 /* Don't allow ".." to appear in a property name */
129 for (size_t i = 0; i < namelen; i++) {
130 if (name[i] == '.') {
131 // i=0 is guaranteed to never have a dot. See above.
132 if (name[i-1] == '.') return false;
133 continue;
134 }
135 if (name[i] == '_' || name[i] == '-' || name[i] == '@' || name[i] == ':') continue;
136 if (name[i] >= 'a' && name[i] <= 'z') continue;
137 if (name[i] >= 'A' && name[i] <= 'Z') continue;
138 if (name[i] >= '0' && name[i] <= '9') continue;
139 return false;
140 }
141
142 return true;
143}
144
145static uint32_t PropertySetImpl(const std::string& name, const std::string& value) {
146 size_t valuelen = value.size(); 124 size_t valuelen = value.size();
147 125
148 if (!is_legal_property_name(name)) { 126 if (!IsLegalPropertyName(name)) {
149 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: bad name"; 127 *error = "Illegal property name";
150 return PROP_ERROR_INVALID_NAME; 128 return PROP_ERROR_INVALID_NAME;
151 } 129 }
152 130
153 if (valuelen >= PROP_VALUE_MAX && !StartsWith(name, "ro.")) { 131 if (valuelen >= PROP_VALUE_MAX && !StartsWith(name, "ro.")) {
154 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: " 132 *error = "Property value too long";
155 << "value too long";
156 return PROP_ERROR_INVALID_VALUE; 133 return PROP_ERROR_INVALID_VALUE;
157 } 134 }
158 135
159 if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) { 136 if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
160 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: " 137 *error = "Value is not a UTF8 encoded string";
161 << "value not a UTF8 encoded string";
162 return PROP_ERROR_INVALID_VALUE; 138 return PROP_ERROR_INVALID_VALUE;
163 } 139 }
164 140
@@ -166,8 +142,7 @@ static uint32_t PropertySetImpl(const std::string& name, const std::string& valu
166 if (pi != nullptr) { 142 if (pi != nullptr) {
167 // ro.* properties are actually "write-once". 143 // ro.* properties are actually "write-once".
168 if (StartsWith(name, "ro.")) { 144 if (StartsWith(name, "ro.")) {
169 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: " 145 *error = "Read-only property was already set";
170 << "property already set";
171 return PROP_ERROR_READ_ONLY_PROPERTY; 146 return PROP_ERROR_READ_ONLY_PROPERTY;
172 } 147 }
173 148
@@ -175,8 +150,7 @@ static uint32_t PropertySetImpl(const std::string& name, const std::string& valu
175 } else { 150 } else {
176 int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen); 151 int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
177 if (rc < 0) { 152 if (rc < 0) {
178 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: " 153 *error = "__system_property_add failed";
179 << "__system_property_add failed";
180 return PROP_ERROR_SET_FAILED; 154 return PROP_ERROR_SET_FAILED;
181 } 155 }
182 } 156 }
@@ -230,8 +204,10 @@ bool PropertyChildReap(pid_t pid) {
230 if (info.pid != pid) { 204 if (info.pid != pid) {
231 return false; 205 return false;
232 } 206 }
233 if (PropertySetImpl(info.name, info.value) != PROP_SUCCESS) { 207 std::string error;
234 LOG(ERROR) << "Failed to set async property " << info.name; 208 if (PropertySet(info.name, info.value, &error) != PROP_SUCCESS) {
209 LOG(ERROR) << "Failed to set async property " << info.name << " to " << info.value << ": "
210 << error;
235 } 211 }
236 property_children.pop(); 212 property_children.pop();
237 if (!property_children.empty()) { 213 if (!property_children.empty()) {
@@ -241,9 +217,9 @@ bool PropertyChildReap(pid_t pid) {
241} 217}
242 218
243static uint32_t PropertySetAsync(const std::string& name, const std::string& value, 219static uint32_t PropertySetAsync(const std::string& name, const std::string& value,
244 PropertyAsyncFunc func) { 220 PropertyAsyncFunc func, std::string* error) {
245 if (value.empty()) { 221 if (value.empty()) {
246 return PropertySetImpl(name, value); 222 return PropertySet(name, value, error);
247 } 223 }
248 224
249 PropertyChildInfo info; 225 PropertyChildInfo info;
@@ -261,30 +237,27 @@ static int RestoreconRecursiveAsync(const std::string& name, const std::string&
261 return selinux_android_restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE); 237 return selinux_android_restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
262} 238}
263 239
264uint32_t PropertySet(const std::string& name, const std::string& value) {
265 if (name == "selinux.restorecon_recursive") {
266 return PropertySetAsync(name, value, RestoreconRecursiveAsync);
267 }
268
269 return PropertySetImpl(name, value);
270}
271
272uint32_t InitPropertySet(const std::string& name, const std::string& value) { 240uint32_t InitPropertySet(const std::string& name, const std::string& value) {
273 if (StartsWith(name, "ctl.")) { 241 if (StartsWith(name, "ctl.")) {
274 LOG(ERROR) << "Do not set ctl. properties from init; call the Service functions directly"; 242 LOG(ERROR) << "InitPropertySet: Do not set ctl. properties from init; call the Service "
243 "functions directly";
244 return PROP_ERROR_INVALID_NAME;
245 }
246 if (name == "selinux.restorecon_recursive") {
247 LOG(ERROR) << "InitPropertySet: Do not set selinux.restorecon_recursive from init; use the "
248 "restorecon builtin directly";
275 return PROP_ERROR_INVALID_NAME; 249 return PROP_ERROR_INVALID_NAME;
276 } 250 }
277 251
278 const char* type = nullptr; 252 uint32_t result = 0;
279 property_info_area->GetPropertyInfo(name.c_str(), nullptr, &type); 253 ucred cr = {.pid = 1, .uid = 0, .gid = 0};
280 254 std::string error;
281 if (type == nullptr || !CheckType(type, value)) { 255 result = HandlePropertySet(name, value, kInitContext.c_str(), cr, &error);
282 LOG(ERROR) << "property_set: name: '" << name << "' type check failed, type: '" 256 if (result != PROP_SUCCESS) {
283 << (type ?: "(null)") << "' value: '" << value << "'"; 257 LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
284 return PROP_ERROR_INVALID_VALUE;
285 } 258 }
286 259
287 return PropertySet(name, value); 260 return result;
288} 261}
289 262
290class SocketConnection { 263class SocketConnection {
@@ -415,9 +388,9 @@ class SocketConnection {
415 388
416// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*. 389// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
417uint32_t HandlePropertySet(const std::string& name, const std::string& value, 390uint32_t HandlePropertySet(const std::string& name, const std::string& value,
418 const std::string& source_context, const ucred& cr) { 391 const std::string& source_context, const ucred& cr, std::string* error) {
419 if (!is_legal_property_name(name)) { 392 if (!IsLegalPropertyName(name)) {
420 LOG(ERROR) << "PropertySet: illegal property name \"" << name << "\""; 393 *error = "Illegal property name";
421 return PROP_ERROR_INVALID_NAME; 394 return PROP_ERROR_INVALID_NAME;
422 } 395 }
423 396
@@ -430,13 +403,11 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value,
430 const char* type = nullptr; 403 const char* type = nullptr;
431 property_info_area->GetPropertyInfo(control_string.c_str(), &target_context, &type); 404 property_info_area->GetPropertyInfo(control_string.c_str(), &target_context, &type);
432 if (!CheckMacPerms(control_string, target_context, source_context.c_str(), cr)) { 405 if (!CheckMacPerms(control_string, target_context, source_context.c_str(), cr)) {
433 LOG(ERROR) << "PropertySet: Unable to " << (name.c_str() + 4) << " service ctl [" 406 *error = StringPrintf("Unable to '%s' service %s", name.c_str() + 4, value.c_str());
434 << value << "]"
435 << " uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid;
436 return PROP_ERROR_HANDLE_CONTROL_MESSAGE; 407 return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
437 } 408 }
438 409
439 handle_control_message(name.c_str() + 4, value.c_str()); 410 HandleControlMessage(name.c_str() + 4, value, cr.pid);
440 return PROP_SUCCESS; 411 return PROP_SUCCESS;
441 } 412 }
442 413
@@ -445,13 +416,13 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value,
445 property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type); 416 property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
446 417
447 if (!CheckMacPerms(name, target_context, source_context.c_str(), cr)) { 418 if (!CheckMacPerms(name, target_context, source_context.c_str(), cr)) {
448 LOG(ERROR) << "PropertySet: permission denied uid:" << cr.uid << " name:" << name; 419 *error = "SELinux permission check failed";
449 return PROP_ERROR_PERMISSION_DENIED; 420 return PROP_ERROR_PERMISSION_DENIED;
450 } 421 }
451 422
452 if (type == nullptr || !CheckType(type, value)) { 423 if (type == nullptr || !CheckType(type, value)) {
453 LOG(ERROR) << "PropertySet: name: '" << name << "' type check failed, type: '" 424 *error = StringPrintf("Property type check failed, value doesn't match expected type '%s'",
454 << (type ?: "(null)") << "' value: '" << value << "'"; 425 (type ?: "(null)"));
455 return PROP_ERROR_INVALID_VALUE; 426 return PROP_ERROR_INVALID_VALUE;
456 } 427 }
457 428
@@ -470,7 +441,11 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value,
470 << process_log_string; 441 << process_log_string;
471 } 442 }
472 443
473 return PropertySet(name, value); 444 if (name == "selinux.restorecon_recursive") {
445 return PropertySetAsync(name, value, RestoreconRecursiveAsync, error);
446 }
447
448 return PropertySet(name, value, error);
474} 449}
475 450
476static void handle_property_set_fd() { 451static void handle_property_set_fd() {
@@ -513,7 +488,16 @@ static void handle_property_set_fd() {
513 prop_name[PROP_NAME_MAX-1] = 0; 488 prop_name[PROP_NAME_MAX-1] = 0;
514 prop_value[PROP_VALUE_MAX-1] = 0; 489 prop_value[PROP_VALUE_MAX-1] = 0;
515 490
516 HandlePropertySet(prop_value, prop_value, socket.source_context(), socket.cred()); 491 const auto& cr = socket.cred();
492 std::string error;
493 uint32_t result =
494 HandlePropertySet(prop_name, prop_value, socket.source_context(), cr, &error);
495 if (result != PROP_SUCCESS) {
496 LOG(ERROR) << "Unable to set property '" << prop_name << "' to '" << prop_value
497 << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
498 << error;
499 }
500
517 break; 501 break;
518 } 502 }
519 503
@@ -527,7 +511,14 @@ static void handle_property_set_fd() {
527 return; 511 return;
528 } 512 }
529 513
530 auto result = HandlePropertySet(name, value, socket.source_context(), socket.cred()); 514 const auto& cr = socket.cred();
515 std::string error;
516 uint32_t result = HandlePropertySet(name, value, socket.source_context(), cr, &error);
517 if (result != PROP_SUCCESS) {
518 LOG(ERROR) << "Unable to set property '" << name << "' to '" << value
519 << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
520 << error;
521 }
531 socket.SendUint32(result); 522 socket.SendUint32(result);
532 break; 523 break;
533 } 524 }
@@ -545,11 +536,17 @@ static bool load_properties_from_file(const char *, const char *);
545 * Filter is used to decide which properties to load: NULL loads all keys, 536 * Filter is used to decide which properties to load: NULL loads all keys,
546 * "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match. 537 * "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match.
547 */ 538 */
548static void load_properties(char *data, const char *filter) 539static void LoadProperties(char* data, const char* filter, const char* filename) {
549{
550 char *key, *value, *eol, *sol, *tmp, *fn; 540 char *key, *value, *eol, *sol, *tmp, *fn;
551 size_t flen = 0; 541 size_t flen = 0;
552 542
543 const char* context = kInitContext.c_str();
544 for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
545 if (StartsWith(filename, path_prefix)) {
546 context = secontext;
547 }
548 }
549
553 if (filter) { 550 if (filter) {
554 flen = strlen(filter); 551 flen = strlen(filter);
555 } 552 }
@@ -596,7 +593,21 @@ static void load_properties(char *data, const char *filter)
596 } 593 }
597 } 594 }
598 595
599 property_set(key, value); 596 if (StartsWith(key, "ctl.") || key == "sys.powerctl"s ||
597 key == "selinux.restorecon_recursive"s) {
598 LOG(ERROR) << "Ignoring disallowed property '" << key
599 << "' with special meaning in prop file '" << filename << "'";
600 continue;
601 }
602
603 uint32_t result = 0;
604 ucred cr = {.pid = 1, .uid = 0, .gid = 0};
605 std::string error;
606 result = HandlePropertySet(key, value, context, cr, &error);
607 if (result != PROP_SUCCESS) {
608 LOG(ERROR) << "Unable to set property '" << key << "' to '" << value
609 << "' in property file '" << filename << "': " << error;
610 }
600 } 611 }
601 } 612 }
602} 613}
@@ -612,7 +623,8 @@ static bool load_properties_from_file(const char* filename, const char* filter)
612 return false; 623 return false;
613 } 624 }
614 file_contents->push_back('\n'); 625 file_contents->push_back('\n');
615 load_properties(file_contents->data(), filter); 626
627 LoadProperties(file_contents->data(), filter, filename);
616 LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)"; 628 LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";
617 return true; 629 return true;
618} 630}
diff --git a/init/property_service.h b/init/property_service.h
index 8161b40e3..29eaaa901 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -32,7 +32,7 @@ struct property_audit_data {
32extern uint32_t (*property_set)(const std::string& name, const std::string& value); 32extern uint32_t (*property_set)(const std::string& name, const std::string& value);
33 33
34uint32_t HandlePropertySet(const std::string& name, const std::string& value, 34uint32_t HandlePropertySet(const std::string& name, const std::string& value,
35 const std::string& source_context, const ucred& cr); 35 const std::string& source_context, const ucred& cr, std::string* error);
36 36
37extern bool PropertyChildReap(pid_t pid); 37extern bool PropertyChildReap(pid_t pid);
38 38
@@ -41,7 +41,6 @@ void property_load_boot_defaults(void);
41void load_persist_props(void); 41void load_persist_props(void);
42void load_system_props(void); 42void load_system_props(void);
43void start_property_service(void); 43void start_property_service(void);
44bool is_legal_property_name(const std::string& name);
45 44
46} // namespace init 45} // namespace init
47} // namespace android 46} // namespace android
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index 95dd34084..c038aff40 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -45,11 +45,13 @@ TEST(property_service, very_long_name_35166374) {
45 // ...so we can send it a malformed request. 45 // ...so we can send it a malformed request.
46 uint32_t msg = PROP_MSG_SETPROP2; 46 uint32_t msg = PROP_MSG_SETPROP2;
47 uint32_t size = 0xffffffff; 47 uint32_t size = 0xffffffff;
48 uint32_t data = 0xdeadbeef;
49 48
50 ASSERT_EQ(static_cast<ssize_t>(sizeof(msg)), send(fd, &msg, sizeof(msg), 0)); 49 ASSERT_EQ(static_cast<ssize_t>(sizeof(msg)), send(fd, &msg, sizeof(msg), 0));
51 ASSERT_EQ(static_cast<ssize_t>(sizeof(size)), send(fd, &size, sizeof(size), 0)); 50 ASSERT_EQ(static_cast<ssize_t>(sizeof(size)), send(fd, &size, sizeof(size), 0));
52 ASSERT_EQ(static_cast<ssize_t>(sizeof(data)), send(fd, &data, sizeof(data), 0)); 51 uint32_t result = 0;
52 ASSERT_EQ(static_cast<ssize_t>(sizeof(result)),
53 TEMP_FAILURE_RETRY(recv(fd, &result, sizeof(result), MSG_WAITALL)));
54 EXPECT_EQ(static_cast<uint32_t>(PROP_ERROR_READ_DATA), result);
53 ASSERT_EQ(0, close(fd)); 55 ASSERT_EQ(0, close(fd));
54} 56}
55 57
diff --git a/init/reboot.cpp b/init/reboot.cpp
index a88a42d74..03ed55a1b 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -20,6 +20,7 @@
20#include <fcntl.h> 20#include <fcntl.h>
21#include <linux/fs.h> 21#include <linux/fs.h>
22#include <mntent.h> 22#include <mntent.h>
23#include <semaphore.h>
23#include <sys/capability.h> 24#include <sys/capability.h>
24#include <sys/cdefs.h> 25#include <sys/cdefs.h>
25#include <sys/ioctl.h> 26#include <sys/ioctl.h>
@@ -50,6 +51,7 @@
50#include <private/android_filesystem_config.h> 51#include <private/android_filesystem_config.h>
51#include <selinux/selinux.h> 52#include <selinux/selinux.h>
52 53
54#include "action_manager.h"
53#include "capabilities.h" 55#include "capabilities.h"
54#include "init.h" 56#include "init.h"
55#include "property_service.h" 57#include "property_service.h"
@@ -88,12 +90,13 @@ class MountEntry {
88 mnt_opts_(entry.mnt_opts) {} 90 mnt_opts_(entry.mnt_opts) {}
89 91
90 bool Umount(bool force) { 92 bool Umount(bool force) {
93 LOG(INFO) << "Unmounting " << mnt_fsname_ << ":" << mnt_dir_ << " opts " << mnt_opts_;
91 int r = umount2(mnt_dir_.c_str(), force ? MNT_FORCE : 0); 94 int r = umount2(mnt_dir_.c_str(), force ? MNT_FORCE : 0);
92 if (r == 0) { 95 if (r == 0) {
93 LOG(INFO) << "umounted " << mnt_fsname_ << ":" << mnt_dir_ << " opts " << mnt_opts_; 96 LOG(INFO) << "Umounted " << mnt_fsname_ << ":" << mnt_dir_ << " opts " << mnt_opts_;
94 return true; 97 return true;
95 } else { 98 } else {
96 PLOG(WARNING) << "cannot umount " << mnt_fsname_ << ":" << mnt_dir_ << " opts " 99 PLOG(WARNING) << "Cannot umount " << mnt_fsname_ << ":" << mnt_dir_ << " opts "
97 << mnt_opts_; 100 << mnt_opts_;
98 return false; 101 return false;
99 } 102 }
@@ -327,39 +330,9 @@ static UmountStat TryUmountAndFsck(bool runFsck, std::chrono::milliseconds timeo
327 return stat; 330 return stat;
328} 331}
329 332
330void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, 333void RebootThread(unsigned int cmd, std::chrono::milliseconds shutdown_timeout, bool runFsck,
331 bool runFsck) { 334 sem_t* reboot_semaphore) {
332 Timer t; 335 Timer t;
333 LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
334
335 // Ensure last reboot reason is reduced to canonical
336 // alias reported in bootloader or system boot reason.
337 size_t skip = 0;
338 std::vector<std::string> reasons = Split(reason, ",");
339 if (reasons.size() >= 2 && reasons[0] == "reboot" &&
340 (reasons[1] == "recovery" || reasons[1] == "bootloader" || reasons[1] == "cold" ||
341 reasons[1] == "hard" || reasons[1] == "warm")) {
342 skip = strlen("reboot,");
343 }
344 property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
345 sync();
346
347 bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
348
349 auto shutdown_timeout = 0ms;
350 if (!SHUTDOWN_ZERO_TIMEOUT) {
351 if (is_thermal_shutdown) {
352 constexpr unsigned int thermal_shutdown_timeout = 1;
353 shutdown_timeout = std::chrono::seconds(thermal_shutdown_timeout);
354 } else {
355 constexpr unsigned int shutdown_timeout_default = 6;
356 auto shutdown_timeout_property = android::base::GetUintProperty(
357 "ro.build.shutdown_timeout", shutdown_timeout_default);
358 shutdown_timeout = std::chrono::seconds(shutdown_timeout_property);
359 }
360 }
361 LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";
362
363 // keep debugging tools until non critical ones are all gone. 336 // keep debugging tools until non critical ones are all gone.
364 const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"}; 337 const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
365 // watchdogd is a vendor specific component but should be alive to complete shutdown safely. 338 // watchdogd is a vendor specific component but should be alive to complete shutdown safely.
@@ -383,7 +356,7 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
383 } 356 }
384 357
385 // remaining operations (specifically fsck) may take a substantial duration 358 // remaining operations (specifically fsck) may take a substantial duration
386 if (cmd == ANDROID_RB_POWEROFF || is_thermal_shutdown) { 359 if (cmd == ANDROID_RB_POWEROFF || cmd == ANDROID_RB_THERMOFF) {
387 TurnOffBacklight(); 360 TurnOffBacklight();
388 } 361 }
389 362
@@ -460,8 +433,77 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
460 UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration()); 433 UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
461 // Follow what linux shutdown is doing: one more sync with little bit delay 434 // Follow what linux shutdown is doing: one more sync with little bit delay
462 sync(); 435 sync();
463 if (!is_thermal_shutdown) std::this_thread::sleep_for(100ms); 436 if (cmd != ANDROID_RB_THERMOFF) std::this_thread::sleep_for(100ms);
464 LogShutdownTime(stat, &t); 437 LogShutdownTime(stat, &t);
438
439 if (reboot_semaphore != nullptr) {
440 sem_post(reboot_semaphore);
441 }
442}
443
444void RunRebootThread(unsigned int cmd, std::chrono::milliseconds shutdown_timeout) {
445 sem_t reboot_semaphore;
446 timespec shutdown_timeout_timespec;
447
448 if (sem_init(&reboot_semaphore, false, 0) == -1 ||
449 clock_gettime(CLOCK_REALTIME, &shutdown_timeout_timespec) == -1) {
450 // These should never fail, but if they do, skip the graceful reboot and reboot immediately.
451 return;
452 }
453
454 std::thread reboot_thread(&RebootThread, cmd, shutdown_timeout, false, &reboot_semaphore);
455 reboot_thread.detach();
456
457 // One extra second than the timeout passed to the thread as there is a final Umount pass
458 // after the timeout is reached.
459 shutdown_timeout_timespec.tv_sec += 1 + shutdown_timeout.count() / 1000;
460
461 int sem_return = 0;
462 while ((sem_return = sem_timedwait(&reboot_semaphore, &shutdown_timeout_timespec)) == -1 &&
463 errno == EINTR) {
464 }
465
466 if (sem_return == -1) {
467 LOG(ERROR) << "Reboot thread timed out";
468 }
469}
470
471void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,
472 bool runFsck) {
473 LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
474
475 // Ensure last reboot reason is reduced to canonical
476 // alias reported in bootloader or system boot reason.
477 size_t skip = 0;
478 std::vector<std::string> reasons = Split(reason, ",");
479 if (reasons.size() >= 2 && reasons[0] == "reboot" &&
480 (reasons[1] == "recovery" || reasons[1] == "bootloader" || reasons[1] == "cold" ||
481 reasons[1] == "hard" || reasons[1] == "warm")) {
482 skip = strlen("reboot,");
483 }
484 property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
485 sync();
486
487 auto shutdown_timeout = 0ms;
488 if (!SHUTDOWN_ZERO_TIMEOUT) {
489 if (cmd == ANDROID_RB_THERMOFF) {
490 constexpr auto kThermalShutdownTimeout = 1s;
491 shutdown_timeout = kThermalShutdownTimeout;
492 } else {
493 constexpr unsigned int kShutdownTimeoutDefault = 6;
494 auto shutdown_timeout_property = android::base::GetUintProperty(
495 "ro.build.shutdown_timeout", kShutdownTimeoutDefault);
496 shutdown_timeout = std::chrono::seconds(shutdown_timeout_property);
497 }
498 }
499 LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";
500
501 if (runFsck) {
502 RebootThread(cmd, shutdown_timeout, true, nullptr);
503 } else {
504 RunRebootThread(cmd, shutdown_timeout);
505 }
506
465 // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it. 507 // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.
466 RebootSystem(cmd, rebootTarget); 508 RebootSystem(cmd, rebootTarget);
467 abort(); 509 abort();
diff --git a/init/service.cpp b/init/service.cpp
index a4e33f7ec..8130e73a9 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -24,7 +24,6 @@
24#include <sys/prctl.h> 24#include <sys/prctl.h>
25#include <sys/resource.h> 25#include <sys/resource.h>
26#include <sys/stat.h> 26#include <sys/stat.h>
27#include <sys/system_properties.h>
28#include <sys/time.h> 27#include <sys/time.h>
29#include <sys/wait.h> 28#include <sys/wait.h>
30#include <termios.h> 29#include <termios.h>
@@ -33,8 +32,6 @@
33#include <android-base/file.h> 32#include <android-base/file.h>
34#include <android-base/logging.h> 33#include <android-base/logging.h>
35#include <android-base/parseint.h> 34#include <android-base/parseint.h>
36#include <android-base/properties.h>
37#include <android-base/scopeguard.h>
38#include <android-base/stringprintf.h> 35#include <android-base/stringprintf.h>
39#include <android-base/strings.h> 36#include <android-base/strings.h>
40#include <hidl-util/FQName.h> 37#include <hidl-util/FQName.h>
@@ -42,15 +39,23 @@
42#include <selinux/selinux.h> 39#include <selinux/selinux.h>
43#include <system/thread_defs.h> 40#include <system/thread_defs.h>
44 41
45#include "init.h"
46#include "property_service.h"
47#include "rlimit_parser.h" 42#include "rlimit_parser.h"
48#include "util.h" 43#include "util.h"
49 44
45#if defined(__ANDROID__)
46#include <sys/system_properties.h>
47
48#include <android-base/properties.h>
49
50#include "init.h"
51#include "property_service.h"
52#else
53#include "host_init_stubs.h"
54#endif
55
50using android::base::boot_clock; 56using android::base::boot_clock;
51using android::base::GetProperty; 57using android::base::GetProperty;
52using android::base::Join; 58using android::base::Join;
53using android::base::make_scope_guard;
54using android::base::ParseInt; 59using android::base::ParseInt;
55using android::base::StartsWith; 60using android::base::StartsWith;
56using android::base::StringPrintf; 61using android::base::StringPrintf;
@@ -189,7 +194,8 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
189 capabilities_(capabilities), 194 capabilities_(capabilities),
190 namespace_flags_(namespace_flags), 195 namespace_flags_(namespace_flags),
191 seclabel_(seclabel), 196 seclabel_(seclabel),
192 onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0), 197 onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
198 "onrestart", {}),
193 keychord_id_(0), 199 keychord_id_(0),
194 ioprio_class_(IoSchedClass_NONE), 200 ioprio_class_(IoSchedClass_NONE),
195 ioprio_pri_(0), 201 ioprio_pri_(0),
@@ -199,9 +205,7 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
199 soft_limit_in_bytes_(-1), 205 soft_limit_in_bytes_(-1),
200 limit_in_bytes_(-1), 206 limit_in_bytes_(-1),
201 start_order_(0), 207 start_order_(0),
202 args_(args) { 208 args_(args) {}
203 onrestart_.InitSingleTrigger("onrestart");
204}
205 209
206void Service::NotifyStateChange(const std::string& new_state) const { 210void Service::NotifyStateChange(const std::string& new_state) const {
207 if ((flags_ & SVC_TEMPORARY) != 0) { 211 if ((flags_ & SVC_TEMPORARY) != 0) {
@@ -1165,7 +1169,7 @@ bool ServiceParser::IsValidName(const std::string& name) const {
1165 // Property values can contain any characters, but may only be a certain length. 1169 // Property values can contain any characters, but may only be a certain length.
1166 // (The latter restriction is needed because `start` and `stop` work by writing 1170 // (The latter restriction is needed because `start` and `stop` work by writing
1167 // the service name to the "ctl.start" and "ctl.stop" properties.) 1171 // the service name to the "ctl.start" and "ctl.stop" properties.)
1168 return is_legal_property_name("init.svc." + name) && name.size() <= PROP_VALUE_MAX; 1172 return IsLegalPropertyName("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
1169} 1173}
1170 1174
1171} // namespace init 1175} // namespace init
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index f3b643ad7..c1846f76d 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -27,12 +27,14 @@
27#include <selinux/android.h> 27#include <selinux/android.h>
28 28
29#include "action.h" 29#include "action.h"
30#include "property_service.h"
31#include "selinux.h"
32#include "util.h" 30#include "util.h"
33 31
34#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 32#if defined(__ANDROID__)
35#include <sys/_system_properties.h> 33#include "property_service.h"
34#include "selinux.h"
35#else
36#include "host_init_stubs.h"
37#endif
36 38
37using android::base::GetExecutablePath; 39using android::base::GetExecutablePath;
38using android::base::Join; 40using android::base::Join;
@@ -47,6 +49,11 @@ namespace init {
47const std::string kInitContext = "u:r:init:s0"; 49const std::string kInitContext = "u:r:init:s0";
48const std::string kVendorContext = "u:r:vendor_init:s0"; 50const std::string kVendorContext = "u:r:vendor_init:s0";
49 51
52const char* const paths_and_secontexts[2][2] = {
53 {"/vendor", kVendorContext.c_str()},
54 {"/odm", kVendorContext.c_str()},
55};
56
50namespace { 57namespace {
51 58
52constexpr size_t kBufferSize = 4096; 59constexpr size_t kBufferSize = 4096;
@@ -83,7 +90,7 @@ std::vector<std::pair<std::string, std::string>> properties_to_set;
83 90
84uint32_t SubcontextPropertySet(const std::string& name, const std::string& value) { 91uint32_t SubcontextPropertySet(const std::string& name, const std::string& value) {
85 properties_to_set.emplace_back(name, value); 92 properties_to_set.emplace_back(name, value);
86 return PROP_SUCCESS; 93 return 0;
87} 94}
88 95
89class SubcontextProcess { 96class SubcontextProcess {
@@ -295,7 +302,11 @@ Result<Success> Subcontext::Execute(const std::vector<std::string>& args) {
295 302
296 for (const auto& property : subcontext_reply->properties_to_set()) { 303 for (const auto& property : subcontext_reply->properties_to_set()) {
297 ucred cr = {.pid = pid_, .uid = 0, .gid = 0}; 304 ucred cr = {.pid = pid_, .uid = 0, .gid = 0};
298 HandlePropertySet(property.name(), property.value(), context_, cr); 305 std::string error;
306 if (HandlePropertySet(property.name(), property.value(), context_, cr, &error) != 0) {
307 LOG(ERROR) << "Subcontext init could not set '" << property.name() << "' to '"
308 << property.value() << "': " << error;
309 }
299 } 310 }
300 311
301 if (subcontext_reply->reply_case() == SubcontextReply::kFailure) { 312 if (subcontext_reply->reply_case() == SubcontextReply::kFailure) {
@@ -343,9 +354,6 @@ Result<std::vector<std::string>> Subcontext::ExpandArgs(const std::vector<std::s
343static std::vector<Subcontext> subcontexts; 354static std::vector<Subcontext> subcontexts;
344 355
345std::vector<Subcontext>* InitializeSubcontexts() { 356std::vector<Subcontext>* InitializeSubcontexts() {
346 static const char* const paths_and_secontexts[][2] = {
347 {"/vendor", kVendorContext.c_str()},
348 };
349 for (const auto& [path_prefix, secontext] : paths_and_secontexts) { 357 for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
350 subcontexts.emplace_back(path_prefix, secontext); 358 subcontexts.emplace_back(path_prefix, secontext);
351 } 359 }
diff --git a/init/subcontext.h b/init/subcontext.h
index 5601b8022..22d7d43bd 100644
--- a/init/subcontext.h
+++ b/init/subcontext.h
@@ -33,6 +33,7 @@ namespace init {
33 33
34extern const std::string kInitContext; 34extern const std::string kInitContext;
35extern const std::string kVendorContext; 35extern const std::string kVendorContext;
36extern const char* const paths_and_secontexts[2][2];
36 37
37class Subcontext { 38class Subcontext {
38 public: 39 public:
diff --git a/init/test_service/Android.bp b/init/test_service/Android.bp
index 63996993a..8bd16a74f 100644
--- a/init/test_service/Android.bp
+++ b/init/test_service/Android.bp
@@ -17,7 +17,10 @@
17cc_binary { 17cc_binary {
18 name: "test_service", 18 name: "test_service",
19 srcs: ["test_service.cpp"], 19 srcs: ["test_service.cpp"],
20 cflags: ["-Wall", "-Werror"], 20 cflags: [
21 "-Wall",
22 "-Werror",
23 ],
21 shared_libs: ["libbase"], 24 shared_libs: ["libbase"],
22 init_rc: ["test_service.rc"], 25 init_rc: ["test_service.rc"],
23} 26}
diff --git a/init/util.cpp b/init/util.cpp
index d80cb1ef6..4455b2eb1 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -33,7 +33,6 @@
33 33
34#include <android-base/file.h> 34#include <android-base/file.h>
35#include <android-base/logging.h> 35#include <android-base/logging.h>
36#include <android-base/properties.h>
37#include <android-base/stringprintf.h> 36#include <android-base/stringprintf.h>
38#include <android-base/strings.h> 37#include <android-base/strings.h>
39#include <android-base/unique_fd.h> 38#include <android-base/unique_fd.h>
@@ -42,7 +41,14 @@
42#include <selinux/android.h> 41#include <selinux/android.h>
43 42
44#include "reboot.h" 43#include "reboot.h"
44
45#if defined(__ANDROID__)
46#include <android-base/properties.h>
47
45#include "selinux.h" 48#include "selinux.h"
49#else
50#include "host_init_stubs.h"
51#endif
46 52
47#ifdef _INIT_INIT_H 53#ifdef _INIT_INIT_H
48#error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals" 54#error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals"
@@ -409,5 +415,30 @@ bool is_android_dt_value_expected(const std::string& sub_path, const std::string
409 return false; 415 return false;
410} 416}
411 417
418bool IsLegalPropertyName(const std::string& name) {
419 size_t namelen = name.size();
420
421 if (namelen < 1) return false;
422 if (name[0] == '.') return false;
423 if (name[namelen - 1] == '.') return false;
424
425 /* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */
426 /* Don't allow ".." to appear in a property name */
427 for (size_t i = 0; i < namelen; i++) {
428 if (name[i] == '.') {
429 // i=0 is guaranteed to never have a dot. See above.
430 if (name[i - 1] == '.') return false;
431 continue;
432 }
433 if (name[i] == '_' || name[i] == '-' || name[i] == '@' || name[i] == ':') continue;
434 if (name[i] >= 'a' && name[i] <= 'z') continue;
435 if (name[i] >= 'A' && name[i] <= 'Z') continue;
436 if (name[i] >= '0' && name[i] <= '9') continue;
437 return false;
438 }
439
440 return true;
441}
442
412} // namespace init 443} // namespace init
413} // namespace android 444} // namespace android
diff --git a/init/util.h b/init/util.h
index 2cfcf6c78..07e4864ac 100644
--- a/init/util.h
+++ b/init/util.h
@@ -62,6 +62,8 @@ const std::string& get_android_dt_dir();
62bool read_android_dt_file(const std::string& sub_path, std::string* dt_content); 62bool read_android_dt_file(const std::string& sub_path, std::string* dt_content);
63bool is_android_dt_value_expected(const std::string& sub_path, const std::string& expected_content); 63bool is_android_dt_value_expected(const std::string& sub_path, const std::string& expected_content);
64 64
65bool IsLegalPropertyName(const std::string& name);
66
65} // namespace init 67} // namespace init
66} // namespace android 68} // namespace android
67 69
diff --git a/libappfuse/Android.bp b/libappfuse/Android.bp
index 29ffe3244..ae1481f72 100644
--- a/libappfuse/Android.bp
+++ b/libappfuse/Android.bp
@@ -19,7 +19,7 @@ cc_library_shared {
19 "FuseBuffer.cc", 19 "FuseBuffer.cc",
20 "FuseBridgeLoop.cc", 20 "FuseBridgeLoop.cc",
21 "EpollController.cc", 21 "EpollController.cc",
22 ] 22 ],
23} 23}
24 24
25cc_test { 25cc_test {
@@ -31,5 +31,5 @@ cc_test {
31 "tests/FuseAppLoopTest.cc", 31 "tests/FuseAppLoopTest.cc",
32 "tests/FuseBridgeLoopTest.cc", 32 "tests/FuseBridgeLoopTest.cc",
33 "tests/FuseBufferTest.cc", 33 "tests/FuseBufferTest.cc",
34 ] 34 ],
35} 35}
diff --git a/libasyncio/Android.bp b/libasyncio/Android.bp
index 9a12f0d2d..8a2afea3d 100644
--- a/libasyncio/Android.bp
+++ b/libasyncio/Android.bp
@@ -16,7 +16,11 @@
16 16
17cc_defaults { 17cc_defaults {
18 name: "libasyncio_defaults", 18 name: "libasyncio_defaults",
19 cflags: ["-Wall", "-Werror", "-Wextra"], 19 cflags: [
20 "-Wall",
21 "-Werror",
22 "-Wextra",
23 ],
20} 24}
21 25
22cc_library { 26cc_library {
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 10a4e4634..4bd01d2cc 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -27,7 +27,6 @@ cc_defaults {
27 27
28 include_dirs: ["external/libunwind/include/tdep"], 28 include_dirs: ["external/libunwind/include/tdep"],
29 29
30
31 target: { 30 target: {
32 darwin: { 31 darwin: {
33 enabled: false, 32 enabled: false,
@@ -41,7 +40,7 @@ cc_defaults {
41 lib64: { 40 lib64: {
42 suffix: "64", 41 suffix: "64",
43 }, 42 },
44 } 43 },
45} 44}
46 45
47libbacktrace_sources = [ 46libbacktrace_sources = [
@@ -83,6 +82,9 @@ cc_library {
83 target: { 82 target: {
84 darwin: { 83 darwin: {
85 enabled: true, 84 enabled: true,
85 shared_libs: [
86 "libbase",
87 ],
86 }, 88 },
87 linux: { 89 linux: {
88 srcs: libbacktrace_sources, 90 srcs: libbacktrace_sources,
@@ -103,7 +105,7 @@ cc_library {
103 "art/runtime", 105 "art/runtime",
104 ], 106 ],
105 107
106 header_libs: [ "jni_headers", ], 108 header_libs: ["jni_headers"],
107 }, 109 },
108 android: { 110 android: {
109 static_libs: ["libasync_safe"], 111 static_libs: ["libasync_safe"],
@@ -111,7 +113,7 @@ cc_library {
111 vendor: { 113 vendor: {
112 cflags: ["-DNO_LIBDEXFILE_SUPPORT"], 114 cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
113 exclude_shared_libs: ["libdexfile"], 115 exclude_shared_libs: ["libdexfile"],
114 } 116 },
115 }, 117 },
116 whole_static_libs: ["libdemangle"], 118 whole_static_libs: ["libdemangle"],
117} 119}
@@ -127,7 +129,7 @@ cc_library_shared {
127 srcs: ["backtrace_testlib.cpp"], 129 srcs: ["backtrace_testlib.cpp"],
128 130
129 shared_libs: [ 131 shared_libs: [
130 "libunwindstack", 132 "libunwindstack",
131 ], 133 ],
132} 134}
133 135
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index dec241c3c..6445a7c51 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -85,14 +85,12 @@ std::string Backtrace::FormatFrameData(size_t frame_num) {
85std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) { 85std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
86 std::string map_name; 86 std::string map_name;
87 if (BacktraceMap::IsValid(frame->map)) { 87 if (BacktraceMap::IsValid(frame->map)) {
88 map_name = frame->map.Name();
88 if (!frame->map.name.empty()) { 89 if (!frame->map.name.empty()) {
89 map_name = frame->map.name.c_str();
90 if (map_name[0] == '[' && map_name[map_name.size() - 1] == ']') { 90 if (map_name[0] == '[' && map_name[map_name.size() - 1] == ']') {
91 map_name.resize(map_name.size() - 1); 91 map_name.resize(map_name.size() - 1);
92 map_name += StringPrintf(":%" PRIPTR "]", frame->map.start); 92 map_name += StringPrintf(":%" PRIPTR "]", frame->map.start);
93 } 93 }
94 } else {
95 map_name = StringPrintf("<anonymous:%" PRIPTR ">", frame->map.start);
96 } 94 }
97 } else { 95 } else {
98 map_name = "<unknown>"; 96 map_name = "<unknown>";
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index c8a500cee..bdae14062 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -24,11 +24,21 @@
24 24
25#include <log/log.h> 25#include <log/log.h>
26 26
27#include <backtrace/backtrace_constants.h> 27#include <android-base/stringprintf.h>
28#include <backtrace/Backtrace.h>
28#include <backtrace/BacktraceMap.h> 29#include <backtrace/BacktraceMap.h>
30#include <backtrace/backtrace_constants.h>
29 31
30#include "thread_utils.h" 32#include "thread_utils.h"
31 33
34using android::base::StringPrintf;
35
36std::string backtrace_map_t::Name() const {
37 if (!name.empty()) return name;
38 if (start == 0 && end == 0) return "";
39 return StringPrintf("<anonymous:%" PRIPTR ">", start);
40}
41
32BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) { 42BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) {
33 if (pid_ < 0) { 43 if (pid_ < 0) {
34 pid_ = getpid(); 44 pid_ = getpid();
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index 7e2e6d05e..711a12a6c 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -52,6 +52,7 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
52 auto process_memory = stack_map->process_memory(); 52 auto process_memory = stack_map->process_memory();
53 unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(), 53 unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
54 regs, stack_map->process_memory()); 54 regs, stack_map->process_memory());
55 unwinder.SetResolveNames(stack_map->ResolveNames());
55 if (stack_map->GetJitDebug() != nullptr) { 56 if (stack_map->GetJitDebug() != nullptr) {
56 unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch()); 57 unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
57 } 58 }
@@ -127,6 +128,22 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
127 return true; 128 return true;
128} 129}
129 130
131bool Backtrace::UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map,
132 const backtrace_stackinfo_t& stack,
133 std::vector<backtrace_frame_data_t>* frames,
134 BacktraceUnwindError* error) {
135 UnwindStackOfflineMap* offline_map = reinterpret_cast<UnwindStackOfflineMap*>(back_map);
136 // Create the process memory from the stack data since this will almost
137 // always be different each unwind.
138 if (!offline_map->CreateProcessMemory(stack)) {
139 if (error != nullptr) {
140 error->error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
141 }
142 return false;
143 }
144 return Backtrace::Unwind(regs, back_map, frames, 0U, nullptr, error);
145}
146
130UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map) 147UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
131 : BacktraceCurrent(pid, tid, map) {} 148 : BacktraceCurrent(pid, tid, map) {}
132 149
@@ -220,12 +237,12 @@ bool UnwindStackOffline::ReadWord(uint64_t, word_t*) {
220Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, 237Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid,
221 const std::vector<backtrace_map_t>& maps, 238 const std::vector<backtrace_map_t>& maps,
222 const backtrace_stackinfo_t& stack) { 239 const backtrace_stackinfo_t& stack) {
223 BacktraceMap* map = BacktraceMap::CreateOffline(pid, maps, stack); 240 std::unique_ptr<UnwindStackOfflineMap> map(
224 if (map == nullptr) { 241 reinterpret_cast<UnwindStackOfflineMap*>(BacktraceMap::CreateOffline(pid, maps)));
242 if (map.get() == nullptr || !map->CreateProcessMemory(stack)) {
225 return nullptr; 243 return nullptr;
226 } 244 }
227 245 return new UnwindStackOffline(arch, pid, tid, map.release(), false);
228 return new UnwindStackOffline(arch, pid, tid, map, false);
229} 246}
230 247
231Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map) { 248Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map) {
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index 6dcc6210f..9c6fed43c 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -127,12 +127,7 @@ bool UnwindStackOfflineMap::Build() {
127 return false; 127 return false;
128} 128}
129 129
130bool UnwindStackOfflineMap::Build(const std::vector<backtrace_map_t>& backtrace_maps, 130bool UnwindStackOfflineMap::Build(const std::vector<backtrace_map_t>& backtrace_maps) {
131 const backtrace_stackinfo_t& stack) {
132 if (stack.start >= stack.end) {
133 return false;
134 }
135
136 for (const backtrace_map_t& map : backtrace_maps) { 131 for (const backtrace_map_t& map : backtrace_maps) {
137 maps_.push_back(map); 132 maps_.push_back(map);
138 } 133 }
@@ -145,6 +140,13 @@ bool UnwindStackOfflineMap::Build(const std::vector<backtrace_map_t>& backtrace_
145 for (const backtrace_map_t& map : maps_) { 140 for (const backtrace_map_t& map : maps_) {
146 maps->Add(map.start, map.end, map.offset, map.flags, map.name, map.load_bias); 141 maps->Add(map.start, map.end, map.offset, map.flags, map.name, map.load_bias);
147 } 142 }
143 return true;
144}
145
146bool UnwindStackOfflineMap::CreateProcessMemory(const backtrace_stackinfo_t& stack) {
147 if (stack.start >= stack.end) {
148 return false;
149 }
148 150
149 // Create the process memory from the stack data. 151 // Create the process memory from the stack data.
150 uint64_t size = stack.end - stack.start; 152 uint64_t size = stack.end - stack.start;
@@ -154,7 +156,6 @@ bool UnwindStackOfflineMap::Build(const std::vector<backtrace_map_t>& backtrace_
154 std::shared_ptr<unwindstack::Memory> shared_memory(memory); 156 std::shared_ptr<unwindstack::Memory> shared_memory(memory);
155 157
156 process_memory_.reset(new unwindstack::MemoryRange(shared_memory, 0, size, stack.start)); 158 process_memory_.reset(new unwindstack::MemoryRange(shared_memory, 0, size, stack.start));
157
158 return true; 159 return true;
159} 160}
160 161
@@ -182,10 +183,9 @@ BacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) {
182//------------------------------------------------------------------------- 183//-------------------------------------------------------------------------
183// BacktraceMap create offline function. 184// BacktraceMap create offline function.
184//------------------------------------------------------------------------- 185//-------------------------------------------------------------------------
185BacktraceMap* BacktraceMap::CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps, 186BacktraceMap* BacktraceMap::CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps) {
186 const backtrace_stackinfo_t& stack) {
187 UnwindStackOfflineMap* map = new UnwindStackOfflineMap(pid); 187 UnwindStackOfflineMap* map = new UnwindStackOfflineMap(pid);
188 if (!map->Build(maps, stack)) { 188 if (!map->Build(maps)) {
189 delete map; 189 delete map;
190 return nullptr; 190 return nullptr;
191 } 191 }
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
index 94cbfb2a0..ec0d9c148 100644
--- a/libbacktrace/UnwindStackMap.h
+++ b/libbacktrace/UnwindStackMap.h
@@ -76,7 +76,9 @@ class UnwindStackOfflineMap : public UnwindStackMap {
76 76
77 bool Build() override; 77 bool Build() override;
78 78
79 bool Build(const std::vector<backtrace_map_t>& maps, const backtrace_stackinfo_t& stack); 79 bool Build(const std::vector<backtrace_map_t>& maps);
80
81 bool CreateProcessMemory(const backtrace_stackinfo_t& stack);
80}; 82};
81 83
82#endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H 84#endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h
index 7a37015d6..a0882079e 100644
--- a/libbacktrace/include/backtrace/Backtrace.h
+++ b/libbacktrace/include/backtrace/Backtrace.h
@@ -151,6 +151,11 @@ class Backtrace {
151 std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames, 151 std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
152 std::vector<std::string>* skip_names, BacktraceUnwindError* error = nullptr); 152 std::vector<std::string>* skip_names, BacktraceUnwindError* error = nullptr);
153 153
154 static bool UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map,
155 const backtrace_stackinfo_t& stack_info,
156 std::vector<backtrace_frame_data_t>* frames,
157 BacktraceUnwindError* error = nullptr);
158
154 // Get the function name and offset into the function given the pc. 159 // Get the function name and offset into the function given the pc.
155 // If the string is empty, then no valid function name was found, 160 // If the string is empty, then no valid function name was found,
156 // or the pc is not in any valid map. 161 // or the pc is not in any valid map.
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h
index e19c41396..473d195ba 100644
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ b/libbacktrace/include/backtrace/BacktraceMap.h
@@ -48,6 +48,9 @@ struct backtrace_map_t {
48 uint64_t load_bias = 0; 48 uint64_t load_bias = 0;
49 int flags = 0; 49 int flags = 0;
50 std::string name; 50 std::string name;
51
52 // Returns `name` if non-empty, or `<anonymous:0x...>` otherwise.
53 std::string Name() const;
51}; 54};
52 55
53namespace unwindstack { 56namespace unwindstack {
@@ -61,8 +64,7 @@ public:
61 // is unsupported. 64 // is unsupported.
62 static BacktraceMap* Create(pid_t pid, bool uncached = false); 65 static BacktraceMap* Create(pid_t pid, bool uncached = false);
63 66
64 static BacktraceMap* CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps, 67 static BacktraceMap* CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps);
65 const backtrace_stackinfo_t& stack);
66 68
67 virtual ~BacktraceMap(); 69 virtual ~BacktraceMap();
68 70
@@ -151,6 +153,13 @@ public:
151 153
152 const std::vector<std::string>& GetSuffixesToIgnore() { return suffixes_to_ignore_; } 154 const std::vector<std::string>& GetSuffixesToIgnore() { return suffixes_to_ignore_; }
153 155
156 // Disabling the resolving of names results in the function name being
157 // set to an empty string and the function offset being set to zero
158 // in the frame data when unwinding.
159 void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
160
161 bool ResolveNames() { return resolve_names_; }
162
154 protected: 163 protected:
155 BacktraceMap(pid_t pid); 164 BacktraceMap(pid_t pid);
156 165
@@ -161,6 +170,7 @@ public:
161 pid_t pid_; 170 pid_t pid_;
162 std::deque<backtrace_map_t> maps_; 171 std::deque<backtrace_map_t> maps_;
163 std::vector<std::string> suffixes_to_ignore_; 172 std::vector<std::string> suffixes_to_ignore_;
173 bool resolve_names_ = true;
164}; 174};
165 175
166class ScopedBacktraceMapIteratorLock { 176class ScopedBacktraceMapIteratorLock {
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index a993d411c..5ea981f7d 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -202,16 +202,6 @@ static const struct fs_path_config android_files[] = {
202 CAP_MASK_LONG(CAP_NET_RAW), 202 CAP_MASK_LONG(CAP_NET_RAW),
203 "vendor/bin/hw/android.hardware.wifi@1.0-service" }, 203 "vendor/bin/hw/android.hardware.wifi@1.0-service" },
204 204
205 // A non-privileged zygote that spawns isolated processes for web rendering.
206 { 0750, AID_ROOT, AID_ROOT, CAP_MASK_LONG(CAP_SETUID) |
207 CAP_MASK_LONG(CAP_SETGID) |
208 CAP_MASK_LONG(CAP_SETPCAP),
209 "system/bin/webview_zygote32" },
210 { 0750, AID_ROOT, AID_ROOT, CAP_MASK_LONG(CAP_SETUID) |
211 CAP_MASK_LONG(CAP_SETGID) |
212 CAP_MASK_LONG(CAP_SETPCAP),
213 "system/bin/webview_zygote64" },
214
215 // generic defaults 205 // generic defaults
216 { 00755, AID_ROOT, AID_ROOT, 0, "bin/*" }, 206 { 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
217 { 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" }, 207 { 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index fcbdc9b79..b2779b2ef 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -72,7 +72,8 @@ __BEGIN_DECLS
72#define ATRACE_TAG_DATABASE (1<<20) 72#define ATRACE_TAG_DATABASE (1<<20)
73#define ATRACE_TAG_NETWORK (1<<21) 73#define ATRACE_TAG_NETWORK (1<<21)
74#define ATRACE_TAG_ADB (1<<22) 74#define ATRACE_TAG_ADB (1<<22)
75#define ATRACE_TAG_LAST ATRACE_TAG_ADB 75#define ATRACE_TAG_VIBRATOR (1<<23)
76#define ATRACE_TAG_LAST ATRACE_TAG_VIBRATOR
76 77
77// Reserved for initialization. 78// Reserved for initialization.
78#define ATRACE_TAG_NOT_READY (1ULL<<63) 79#define ATRACE_TAG_NOT_READY (1ULL<<63)
diff --git a/libion/Android.bp b/libion/Android.bp
index 6d9fae076..2f73d92ca 100644
--- a/libion/Android.bp
+++ b/libion/Android.bp
@@ -1,4 +1,3 @@
1
2cc_library { 1cc_library {
3 name: "libion", 2 name: "libion",
4 vendor_available: true, 3 vendor_available: true,
diff --git a/libion/ion_test.c b/libion/ion_test.c
index b7d558354..f3874aefb 100644
--- a/libion/ion_test.c
+++ b/libion/ion_test.c
@@ -250,7 +250,7 @@ int main(int argc, char* argv[]) {
250 case 'p': 250 case 'p':
251 prot = 0; 251 prot = 0;
252 prot |= strstr(optarg, "MAP_PRIVATE") ? MAP_PRIVATE : 0; 252 prot |= strstr(optarg, "MAP_PRIVATE") ? MAP_PRIVATE : 0;
253 prot |= strstr(optarg, "MAP_SHARED") ? MAP_PRIVATE : 0; 253 prot |= strstr(optarg, "MAP_SHARED") ? MAP_SHARED : 0;
254 break; 254 break;
255 case 'f': 255 case 'f':
256 alloc_flags = atol(optarg); 256 alloc_flags = atol(optarg);
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index ade282187..28c87e46d 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -171,6 +171,36 @@ void __android_log_assert(const char* cond, const char* tag, const char* fmt,
171#endif 171#endif
172 ; 172 ;
173 173
174#ifndef log_id_t_defined
175#define log_id_t_defined
176typedef enum log_id {
177 LOG_ID_MIN = 0,
178
179 LOG_ID_MAIN = 0,
180 LOG_ID_RADIO = 1,
181 LOG_ID_EVENTS = 2,
182 LOG_ID_SYSTEM = 3,
183 LOG_ID_CRASH = 4,
184 LOG_ID_STATS = 5,
185 LOG_ID_SECURITY = 6,
186 LOG_ID_KERNEL = 7, /* place last, third-parties can not use it */
187
188 LOG_ID_MAX
189} log_id_t;
190#endif
191
192/*
193 * Send a simple string to the log.
194 */
195int __android_log_buf_write(int bufID, int prio, const char* tag,
196 const char* text);
197int __android_log_buf_print(int bufID, int prio, const char* tag,
198 const char* fmt, ...)
199#if defined(__GNUC__)
200 __attribute__((__format__(printf, 4, 5)))
201#endif
202 ;
203
174#ifdef __cplusplus 204#ifdef __cplusplus
175} 205}
176#endif 206#endif
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 9d21e56eb..66670fe28 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -3,8 +3,8 @@ LIBLOG {
3 android_name_to_log_id; # vndk 3 android_name_to_log_id; # vndk
4 android_log_id_to_name; # vndk 4 android_log_id_to_name; # vndk
5 __android_log_assert; 5 __android_log_assert;
6 __android_log_buf_print; # vndk 6 __android_log_buf_print;
7 __android_log_buf_write; # vndk 7 __android_log_buf_write;
8 __android_log_print; 8 __android_log_print;
9 __android_log_vprint; 9 __android_log_vprint;
10 __android_log_write; 10 __android_log_write;
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
index 8b76a6513..caca3774e 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -16,11 +16,11 @@ cc_defaults {
16 }, 16 },
17 host: { 17 host: {
18 shared_libs: ["liblog"], 18 shared_libs: ["liblog"],
19 } 19 },
20 }, 20 },
21} 21}
22 22
23cc_library_shared { 23cc_library {
24 name: "libmemunreachable", 24 name: "libmemunreachable",
25 defaults: ["libmemunreachable_defaults"], 25 defaults: ["libmemunreachable_defaults"],
26 srcs: [ 26 srcs: [
@@ -88,14 +88,14 @@ cc_test {
88cc_test { 88cc_test {
89 name: "memunreachable_binder_test", 89 name: "memunreachable_binder_test",
90 defaults: ["libmemunreachable_defaults"], 90 defaults: ["libmemunreachable_defaults"],
91 test_suites: ["vts"],
91 srcs: [ 92 srcs: [
92 "tests/Binder_test.cpp", 93 "tests/Binder_test.cpp",
93 "tests/MemUnreachable_test.cpp",
94 ], 94 ],
95 static_libs: ["libmemunreachable"],
95 shared_libs: [ 96 shared_libs: [
96 "libbinder", 97 "libbinder",
97 "libhwbinder", 98 "libhwbinder",
98 "libmemunreachable",
99 "libutils", 99 "libutils",
100 ], 100 ],
101} 101}
diff --git a/libmemunreachable/tests/Binder_test.cpp b/libmemunreachable/tests/Binder_test.cpp
index 6e85d5ab3..eaf7652d1 100644
--- a/libmemunreachable/tests/Binder_test.cpp
+++ b/libmemunreachable/tests/Binder_test.cpp
@@ -33,6 +33,9 @@ namespace android {
33 33
34static const String16 service_name("test.libmemunreachable_binder"); 34static const String16 service_name("test.libmemunreachable_binder");
35 35
36// Provides a service that will hold a strong reference to any remote binder
37// object, so that the test can verify that a remote strong reference is
38// visible to libmemunreachable.
36class BinderService : public BBinder { 39class BinderService : public BBinder {
37 public: 40 public:
38 BinderService() = default; 41 BinderService() = default;
@@ -55,6 +58,8 @@ class BinderObject : public BBinder {
55 ~BinderObject() = default; 58 ~BinderObject() = default;
56}; 59};
57 60
61// Forks a subprocess that registers a BinderService with the global binder
62// servicemanager. Requires root permissions.
58class ServiceProcess { 63class ServiceProcess {
59 public: 64 public:
60 ServiceProcess() : child_(0) {} 65 ServiceProcess() : child_(0) {}
@@ -97,6 +102,7 @@ class ServiceProcess {
97 fprintf(stderr, "Failed to get service manager\n"); 102 fprintf(stderr, "Failed to get service manager\n");
98 return 1; 103 return 1;
99 } 104 }
105 // This step requires root permissions
100 if (sm->addService(service_name, new BinderService()) != OK) { 106 if (sm->addService(service_name, new BinderService()) != OK) {
101 fprintf(stderr, "Failed to add test service\n"); 107 fprintf(stderr, "Failed to add test service\n");
102 return 1; 108 return 1;
@@ -110,12 +116,18 @@ class ServiceProcess {
110 pid_t child_; 116 pid_t child_;
111}; 117};
112 118
113class BinderTest : public ::testing::Test { 119class MemunreachableBinderTest : public ::testing::Test {
114 protected: 120 protected:
115 ServiceProcess service_process_; 121 ServiceProcess service_process_;
116}; 122};
117 123
118TEST_F(BinderTest, binder) { 124// Tests that a local binder object with a remote strong reference is visible
125// through the libmemunreachable BinderReferences interface, which uses the
126// getBinderKernelReferences method in libbinder. Starts a BinderService
127// through ServiceProcess as a remote service to hold the strong reference.
128TEST_F(MemunreachableBinderTest, binder) {
129 ASSERT_EQ(static_cast<uid_t>(0), getuid()) << "This test must be run as root.";
130
119 ServiceProcess service_process; 131 ServiceProcess service_process;
120 ASSERT_TRUE(service_process.Run()); 132 ASSERT_TRUE(service_process.Run());
121 133
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 089f3b825..6e63b74c6 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -1,9 +1,8 @@
1
2cc_library_headers { 1cc_library_headers {
3 name: "libnativebridge-dummy-headers", 2 name: "libnativebridge-dummy-headers",
4 3
5 host_supported: true, 4 host_supported: true,
6 export_include_dirs=["include"], 5 export_include_dirs: ["include"],
7} 6}
8 7
9cc_library { 8cc_library {
@@ -11,9 +10,12 @@ cc_library {
11 10
12 host_supported: true, 11 host_supported: true,
13 srcs: ["native_bridge.cc"], 12 srcs: ["native_bridge.cc"],
14 shared_libs: ["liblog", "libbase"], 13 shared_libs: [
14 "liblog",
15 "libbase",
16 ],
15 17
16 export_include_dirs=["include"], 18 export_include_dirs: ["include"],
17 19
18 cflags: [ 20 cflags: [
19 "-Werror", 21 "-Werror",
diff --git a/libnativeloader/test/Android.bp b/libnativeloader/test/Android.bp
index 2d3370435..5cf88b09b 100644
--- a/libnativeloader/test/Android.bp
+++ b/libnativeloader/test/Android.bp
@@ -17,31 +17,34 @@
17cc_library { 17cc_library {
18 name: "libfoo.oem1", 18 name: "libfoo.oem1",
19 srcs: ["test.cpp"], 19 srcs: ["test.cpp"],
20 cflags : ["-DLIBNAME=\"libfoo.oem1.so\""], 20 cflags: ["-DLIBNAME=\"libfoo.oem1.so\""],
21 shared_libs: [ 21 shared_libs: [
22 "libbase", 22 "libbase",
23 ], 23 ],
24} 24}
25
25cc_library { 26cc_library {
26 name: "libbar.oem1", 27 name: "libbar.oem1",
27 srcs: ["test.cpp"], 28 srcs: ["test.cpp"],
28 cflags : ["-DLIBNAME=\"libbar.oem1.so\""], 29 cflags: ["-DLIBNAME=\"libbar.oem1.so\""],
29 shared_libs: [ 30 shared_libs: [
30 "libbase", 31 "libbase",
31 ], 32 ],
32} 33}
34
33cc_library { 35cc_library {
34 name: "libfoo.oem2", 36 name: "libfoo.oem2",
35 srcs: ["test.cpp"], 37 srcs: ["test.cpp"],
36 cflags : ["-DLIBNAME=\"libfoo.oem2.so\""], 38 cflags: ["-DLIBNAME=\"libfoo.oem2.so\""],
37 shared_libs: [ 39 shared_libs: [
38 "libbase", 40 "libbase",
39 ], 41 ],
40} 42}
43
41cc_library { 44cc_library {
42 name: "libbar.oem2", 45 name: "libbar.oem2",
43 srcs: ["test.cpp"], 46 srcs: ["test.cpp"],
44 cflags : ["-DLIBNAME=\"libbar.oem2.so\""], 47 cflags: ["-DLIBNAME=\"libbar.oem2.so\""],
45 shared_libs: [ 48 shared_libs: [
46 "libbase", 49 "libbase",
47 ], 50 ],
diff --git a/libpackagelistparser/Android.bp b/libpackagelistparser/Android.bp
index 3d202fc1d..27693b3f8 100644
--- a/libpackagelistparser/Android.bp
+++ b/libpackagelistparser/Android.bp
@@ -2,7 +2,10 @@ cc_library {
2 2
3 name: "libpackagelistparser", 3 name: "libpackagelistparser",
4 srcs: ["packagelistparser.c"], 4 srcs: ["packagelistparser.c"],
5 cflags: ["-Wall", "-Werror"], 5 cflags: [
6 "-Wall",
7 "-Werror",
8 ],
6 shared_libs: ["liblog"], 9 shared_libs: ["liblog"],
7 local_include_dirs: ["include"], 10 local_include_dirs: ["include"],
8 export_include_dirs: ["include"], 11 export_include_dirs: ["include"],
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index 1974f2c2b..b0bc497ab 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -1,7 +1,7 @@
1cc_library { 1cc_library {
2 srcs: ["processgroup.cpp"], 2 srcs: ["processgroup.cpp"],
3 name: "libprocessgroup", 3 name: "libprocessgroup",
4 defaults: ["linux_bionic_supported"], 4 host_supported: true,
5 shared_libs: ["libbase"], 5 shared_libs: ["libbase"],
6 export_include_dirs: ["include"], 6 export_include_dirs: ["include"],
7 cflags: [ 7 cflags: [
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 8526b3a29..6dfa697de 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -22,6 +22,7 @@
22#include <errno.h> 22#include <errno.h>
23#include <fcntl.h> 23#include <fcntl.h>
24#include <inttypes.h> 24#include <inttypes.h>
25#include <signal.h>
25#include <stdio.h> 26#include <stdio.h>
26#include <stdlib.h> 27#include <stdlib.h>
27#include <string.h> 28#include <string.h>
@@ -33,15 +34,19 @@
33#include <memory> 34#include <memory>
34#include <mutex> 35#include <mutex>
35#include <set> 36#include <set>
37#include <string>
36#include <thread> 38#include <thread>
37 39
38#include <android-base/file.h> 40#include <android-base/file.h>
39#include <android-base/logging.h> 41#include <android-base/logging.h>
40#include <android-base/unique_fd.h> 42#include <android-base/stringprintf.h>
43#include <android-base/strings.h>
41#include <private/android_filesystem_config.h> 44#include <private/android_filesystem_config.h>
42 45
43#include <processgroup/processgroup.h> 46#include <processgroup/processgroup.h>
44 47
48using android::base::StartsWith;
49using android::base::StringPrintf;
45using android::base::WriteStringToFile; 50using android::base::WriteStringToFile;
46 51
47using namespace std::chrono_literals; 52using namespace std::chrono_literals;
@@ -50,171 +55,58 @@ using namespace std::chrono_literals;
50#define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks" 55#define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks"
51#define ACCT_CGROUP_PATH "/acct" 56#define ACCT_CGROUP_PATH "/acct"
52 57
53#define PROCESSGROUP_UID_PREFIX "uid_"
54#define PROCESSGROUP_PID_PREFIX "pid_"
55#define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs" 58#define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs"
56#define PROCESSGROUP_MAX_UID_LEN 11
57#define PROCESSGROUP_MAX_PID_LEN 11
58#define PROCESSGROUP_MAX_PATH_LEN \
59 ((sizeof(MEM_CGROUP_PATH) > sizeof(ACCT_CGROUP_PATH) ? \
60 sizeof(MEM_CGROUP_PATH) : sizeof(ACCT_CGROUP_PATH)) + \
61 sizeof(PROCESSGROUP_UID_PREFIX) + 1 + \
62 PROCESSGROUP_MAX_UID_LEN + \
63 sizeof(PROCESSGROUP_PID_PREFIX) + 1 + \
64 PROCESSGROUP_MAX_PID_LEN + \
65 sizeof(PROCESSGROUP_CGROUP_PROCS_FILE) + \
66 1)
67 59
68std::once_flag init_path_flag; 60std::once_flag init_path_flag;
69 61
70class ProcessGroup { 62static const std::string& GetCgroupRootPath() {
71 public: 63 static std::string cgroup_root_path;
72 ProcessGroup() : buf_ptr_(buf_), buf_len_(0) {}
73
74 bool Open(uid_t uid, int pid);
75
76 // Return positive number and sets *pid = next pid in process cgroup on success
77 // Returns 0 if there are no pids left in the process cgroup
78 // Returns -errno if an error was encountered
79 int GetOneAppProcess(pid_t* pid);
80
81 private:
82 // Returns positive number of bytes filled on success
83 // Returns 0 if there was nothing to read
84 // Returns -errno if an error was encountered
85 int RefillBuffer();
86
87 android::base::unique_fd fd_;
88 char buf_[128];
89 char* buf_ptr_;
90 size_t buf_len_;
91};
92
93static const char* getCgroupRootPath() {
94 static const char* cgroup_root_path = NULL;
95 std::call_once(init_path_flag, [&]() { 64 std::call_once(init_path_flag, [&]() {
96 // Check if mem cgroup is mounted, only then check for write-access to avoid 65 // Check if mem cgroup is mounted, only then check for write-access to avoid
97 // SELinux denials 66 // SELinux denials
98 cgroup_root_path = access(MEM_CGROUP_TASKS, F_OK) || access(MEM_CGROUP_PATH, W_OK) ? 67 cgroup_root_path =
99 ACCT_CGROUP_PATH : MEM_CGROUP_PATH; 68 (access(MEM_CGROUP_TASKS, F_OK) || access(MEM_CGROUP_PATH, W_OK) ? ACCT_CGROUP_PATH
69 : MEM_CGROUP_PATH);
100 }); 70 });
101 return cgroup_root_path; 71 return cgroup_root_path;
102} 72}
103 73
104static int convertUidToPath(char *path, size_t size, uid_t uid) 74static std::string ConvertUidToPath(uid_t uid) {
105{ 75 return StringPrintf("%s/uid_%d", GetCgroupRootPath().c_str(), uid);
106 return snprintf(path, size, "%s/%s%d",
107 getCgroupRootPath(),
108 PROCESSGROUP_UID_PREFIX,
109 uid);
110}
111
112static int convertUidPidToPath(char *path, size_t size, uid_t uid, int pid)
113{
114 return snprintf(path, size, "%s/%s%d/%s%d",
115 getCgroupRootPath(),
116 PROCESSGROUP_UID_PREFIX,
117 uid,
118 PROCESSGROUP_PID_PREFIX,
119 pid);
120}
121
122bool ProcessGroup::Open(uid_t uid, int pid) {
123 char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
124 convertUidPidToPath(path, sizeof(path), uid, pid);
125 strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
126
127 int fd = open(path, O_RDONLY);
128 if (fd < 0) return false;
129
130 fd_.reset(fd);
131
132 LOG(VERBOSE) << "Initialized context for " << path;
133
134 return true;
135}
136
137int ProcessGroup::RefillBuffer() {
138 memmove(buf_, buf_ptr_, buf_len_);
139 buf_ptr_ = buf_;
140
141 ssize_t ret = read(fd_, buf_ptr_ + buf_len_, sizeof(buf_) - buf_len_ - 1);
142 if (ret < 0) {
143 return -errno;
144 } else if (ret == 0) {
145 return 0;
146 }
147
148 buf_len_ += ret;
149 buf_[buf_len_] = 0;
150 LOG(VERBOSE) << "Read " << ret << " to buffer: " << buf_;
151
152 assert(buf_len_ <= sizeof(buf_));
153
154 return ret;
155} 76}
156 77
157int ProcessGroup::GetOneAppProcess(pid_t* out_pid) { 78static std::string ConvertUidPidToPath(uid_t uid, int pid) {
158 *out_pid = 0; 79 return StringPrintf("%s/uid_%d/pid_%d", GetCgroupRootPath().c_str(), uid, pid);
159
160 char* eptr;
161 while ((eptr = static_cast<char*>(memchr(buf_ptr_, '\n', buf_len_))) == nullptr) {
162 int ret = RefillBuffer();
163 if (ret <= 0) return ret;
164 }
165
166 *eptr = '\0';
167 char* pid_eptr = nullptr;
168 errno = 0;
169 long pid = strtol(buf_ptr_, &pid_eptr, 10);
170 if (errno != 0) {
171 return -errno;
172 }
173 if (pid_eptr != eptr) {
174 errno = EINVAL;
175 return -errno;
176 }
177
178 buf_len_ -= (eptr - buf_ptr_) + 1;
179 buf_ptr_ = eptr + 1;
180
181 *out_pid = static_cast<pid_t>(pid);
182 return 1;
183} 80}
184 81
185static int removeProcessGroup(uid_t uid, int pid) 82static int RemoveProcessGroup(uid_t uid, int pid) {
186{
187 int ret; 83 int ret;
188 char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
189 84
190 convertUidPidToPath(path, sizeof(path), uid, pid); 85 auto uid_pid_path = ConvertUidPidToPath(uid, pid);
191 ret = rmdir(path); 86 ret = rmdir(uid_pid_path.c_str());
192 87
193 convertUidToPath(path, sizeof(path), uid); 88 auto uid_path = ConvertUidToPath(uid);
194 rmdir(path); 89 rmdir(uid_path.c_str());
195 90
196 return ret; 91 return ret;
197} 92}
198 93
199static void removeUidProcessGroups(const char *uid_path) 94static void RemoveUidProcessGroups(const std::string& uid_path) {
200{ 95 std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path.c_str()), closedir);
201 std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path), closedir);
202 if (uid != NULL) { 96 if (uid != NULL) {
203 dirent* dir; 97 dirent* dir;
204 while ((dir = readdir(uid.get())) != nullptr) { 98 while ((dir = readdir(uid.get())) != nullptr) {
205 char path[PROCESSGROUP_MAX_PATH_LEN];
206
207 if (dir->d_type != DT_DIR) { 99 if (dir->d_type != DT_DIR) {
208 continue; 100 continue;
209 } 101 }
210 102
211 if (strncmp(dir->d_name, PROCESSGROUP_PID_PREFIX, strlen(PROCESSGROUP_PID_PREFIX))) { 103 if (!StartsWith(dir->d_name, "pid_")) {
212 continue; 104 continue;
213 } 105 }
214 106
215 snprintf(path, sizeof(path), "%s/%s", uid_path, dir->d_name); 107 auto path = StringPrintf("%s/%s", uid_path.c_str(), dir->d_name);
216 LOG(VERBOSE) << "Removing " << path; 108 LOG(VERBOSE) << "Removing " << path;
217 if (rmdir(path) == -1) PLOG(WARNING) << "Failed to remove " << path; 109 if (rmdir(path.c_str()) == -1) PLOG(WARNING) << "Failed to remove " << path;
218 } 110 }
219 } 111 }
220} 112}
@@ -222,38 +114,38 @@ static void removeUidProcessGroups(const char *uid_path)
222void removeAllProcessGroups() 114void removeAllProcessGroups()
223{ 115{
224 LOG(VERBOSE) << "removeAllProcessGroups()"; 116 LOG(VERBOSE) << "removeAllProcessGroups()";
225 const char* cgroup_root_path = getCgroupRootPath(); 117 const auto& cgroup_root_path = GetCgroupRootPath();
226 std::unique_ptr<DIR, decltype(&closedir)> root(opendir(cgroup_root_path), closedir); 118 std::unique_ptr<DIR, decltype(&closedir)> root(opendir(cgroup_root_path.c_str()), closedir);
227 if (root == NULL) { 119 if (root == NULL) {
228 PLOG(ERROR) << "Failed to open " << cgroup_root_path; 120 PLOG(ERROR) << "Failed to open " << cgroup_root_path;
229 } else { 121 } else {
230 dirent* dir; 122 dirent* dir;
231 while ((dir = readdir(root.get())) != nullptr) { 123 while ((dir = readdir(root.get())) != nullptr) {
232 char path[PROCESSGROUP_MAX_PATH_LEN];
233
234 if (dir->d_type != DT_DIR) { 124 if (dir->d_type != DT_DIR) {
235 continue; 125 continue;
236 } 126 }
237 if (strncmp(dir->d_name, PROCESSGROUP_UID_PREFIX, strlen(PROCESSGROUP_UID_PREFIX))) { 127
128 if (!StartsWith(dir->d_name, "uid_")) {
238 continue; 129 continue;
239 } 130 }
240 131
241 snprintf(path, sizeof(path), "%s/%s", cgroup_root_path, dir->d_name); 132 auto path = StringPrintf("%s/%s", cgroup_root_path.c_str(), dir->d_name);
242 removeUidProcessGroups(path); 133 RemoveUidProcessGroups(path);
243 LOG(VERBOSE) << "Removing " << path; 134 LOG(VERBOSE) << "Removing " << path;
244 if (rmdir(path) == -1) PLOG(WARNING) << "Failed to remove " << path; 135 if (rmdir(path.c_str()) == -1) PLOG(WARNING) << "Failed to remove " << path;
245 } 136 }
246 } 137 }
247} 138}
248 139
249// Returns number of processes killed on success 140// Returns number of processes killed on success
250// Returns 0 if there are no processes in the process cgroup left to kill 141// Returns 0 if there are no processes in the process cgroup left to kill
251// Returns -errno on error 142// Returns -1 on error
252static int doKillProcessGroupOnce(uid_t uid, int initialPid, int signal) { 143static int DoKillProcessGroupOnce(uid_t uid, int initialPid, int signal) {
253 ProcessGroup process_group; 144 auto path = ConvertUidPidToPath(uid, initialPid) + PROCESSGROUP_CGROUP_PROCS_FILE;
254 if (!process_group.Open(uid, initialPid)) { 145 std::unique_ptr<FILE, decltype(&fclose)> fd(fopen(path.c_str(), "re"), fclose);
146 if (!fd) {
255 PLOG(WARNING) << "Failed to open process cgroup uid " << uid << " pid " << initialPid; 147 PLOG(WARNING) << "Failed to open process cgroup uid " << uid << " pid " << initialPid;
256 return -errno; 148 return -1;
257 } 149 }
258 150
259 // We separate all of the pids in the cgroup into those pids that are also the leaders of 151 // We separate all of the pids in the cgroup into those pids that are also the leaders of
@@ -262,10 +154,9 @@ static int doKillProcessGroupOnce(uid_t uid, int initialPid, int signal) {
262 pgids.emplace(initialPid); 154 pgids.emplace(initialPid);
263 std::set<pid_t> pids; 155 std::set<pid_t> pids;
264 156
265 int ret;
266 pid_t pid; 157 pid_t pid;
267 int processes = 0; 158 int processes = 0;
268 while ((ret = process_group.GetOneAppProcess(&pid)) > 0 && pid >= 0) { 159 while (fscanf(fd.get(), "%d\n", &pid) == 1 && pid >= 0) {
269 processes++; 160 processes++;
270 if (pid == 0) { 161 if (pid == 0) {
271 // Should never happen... but if it does, trying to kill this 162 // Should never happen... but if it does, trying to kill this
@@ -312,15 +203,15 @@ static int doKillProcessGroupOnce(uid_t uid, int initialPid, int signal) {
312 } 203 }
313 } 204 }
314 205
315 return ret >= 0 ? processes : ret; 206 return feof(fd.get()) ? processes : -1;
316} 207}
317 208
318static int killProcessGroup(uid_t uid, int initialPid, int signal, int retries) { 209static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) {
319 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); 210 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
320 211
321 int retry = retries; 212 int retry = retries;
322 int processes; 213 int processes;
323 while ((processes = doKillProcessGroupOnce(uid, initialPid, signal)) > 0) { 214 while ((processes = DoKillProcessGroupOnce(uid, initialPid, signal)) > 0) {
324 LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid; 215 LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid;
325 if (retry > 0) { 216 if (retry > 0) {
326 std::this_thread::sleep_for(5ms); 217 std::this_thread::sleep_for(5ms);
@@ -350,7 +241,7 @@ static int killProcessGroup(uid_t uid, int initialPid, int signal, int retries)
350 LOG(INFO) << "Successfully killed process cgroup uid " << uid << " pid " << initialPid 241 LOG(INFO) << "Successfully killed process cgroup uid " << uid << " pid " << initialPid
351 << " in " << static_cast<int>(ms) << "ms"; 242 << " in " << static_cast<int>(ms) << "ms";
352 } 243 }
353 return removeProcessGroup(uid, initialPid); 244 return RemoveProcessGroup(uid, initialPid);
354 } else { 245 } else {
355 if (retries > 0) { 246 if (retries > 0) {
356 LOG(ERROR) << "Failed to kill process cgroup uid " << uid << " pid " << initialPid 247 LOG(ERROR) << "Failed to kill process cgroup uid " << uid << " pid " << initialPid
@@ -362,22 +253,21 @@ static int killProcessGroup(uid_t uid, int initialPid, int signal, int retries)
362} 253}
363 254
364int killProcessGroup(uid_t uid, int initialPid, int signal) { 255int killProcessGroup(uid_t uid, int initialPid, int signal) {
365 return killProcessGroup(uid, initialPid, signal, 40 /*retries*/); 256 return KillProcessGroup(uid, initialPid, signal, 40 /*retries*/);
366} 257}
367 258
368int killProcessGroupOnce(uid_t uid, int initialPid, int signal) { 259int killProcessGroupOnce(uid_t uid, int initialPid, int signal) {
369 return killProcessGroup(uid, initialPid, signal, 0 /*retries*/); 260 return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/);
370} 261}
371 262
372static bool mkdirAndChown(const char *path, mode_t mode, uid_t uid, gid_t gid) 263static bool MkdirAndChown(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
373{ 264 if (mkdir(path.c_str(), mode) == -1 && errno != EEXIST) {
374 if (mkdir(path, mode) == -1 && errno != EEXIST) {
375 return false; 265 return false;
376 } 266 }
377 267
378 if (chown(path, uid, gid) == -1) { 268 if (chown(path.c_str(), uid, gid) == -1) {
379 int saved_errno = errno; 269 int saved_errno = errno;
380 rmdir(path); 270 rmdir(path.c_str());
381 errno = saved_errno; 271 errno = saved_errno;
382 return false; 272 return false;
383 } 273 }
@@ -387,42 +277,38 @@ static bool mkdirAndChown(const char *path, mode_t mode, uid_t uid, gid_t gid)
387 277
388int createProcessGroup(uid_t uid, int initialPid) 278int createProcessGroup(uid_t uid, int initialPid)
389{ 279{
390 char path[PROCESSGROUP_MAX_PATH_LEN] = {0}; 280 auto uid_path = ConvertUidToPath(uid);
391
392 convertUidToPath(path, sizeof(path), uid);
393 281
394 if (!mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM)) { 282 if (!MkdirAndChown(uid_path, 0750, AID_SYSTEM, AID_SYSTEM)) {
395 PLOG(ERROR) << "Failed to make and chown " << path; 283 PLOG(ERROR) << "Failed to make and chown " << uid_path;
396 return -errno; 284 return -errno;
397 } 285 }
398 286
399 convertUidPidToPath(path, sizeof(path), uid, initialPid); 287 auto uid_pid_path = ConvertUidPidToPath(uid, initialPid);
400 288
401 if (!mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM)) { 289 if (!MkdirAndChown(uid_pid_path, 0750, AID_SYSTEM, AID_SYSTEM)) {
402 PLOG(ERROR) << "Failed to make and chown " << path; 290 PLOG(ERROR) << "Failed to make and chown " << uid_pid_path;
403 return -errno; 291 return -errno;
404 } 292 }
405 293
406 strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path)); 294 auto uid_pid_procs_file = uid_pid_path + PROCESSGROUP_CGROUP_PROCS_FILE;
407 295
408 int ret = 0; 296 int ret = 0;
409 if (!WriteStringToFile(std::to_string(initialPid), path)) { 297 if (!WriteStringToFile(std::to_string(initialPid), uid_pid_procs_file)) {
410 ret = -errno; 298 ret = -errno;
411 PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << path; 299 PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << uid_pid_procs_file;
412 } 300 }
413 301
414 return ret; 302 return ret;
415} 303}
416 304
417static bool setProcessGroupValue(uid_t uid, int pid, const char* fileName, int64_t value) { 305static bool SetProcessGroupValue(uid_t uid, int pid, const std::string& file_name, int64_t value) {
418 char path[PROCESSGROUP_MAX_PATH_LEN] = {0}; 306 if (GetCgroupRootPath() != MEM_CGROUP_PATH) {
419 if (strcmp(getCgroupRootPath(), MEM_CGROUP_PATH)) { 307 PLOG(ERROR) << "Memcg is not mounted.";
420 PLOG(ERROR) << "Memcg is not mounted." << path;
421 return false; 308 return false;
422 } 309 }
423 310
424 convertUidPidToPath(path, sizeof(path), uid, pid); 311 auto path = ConvertUidPidToPath(uid, pid) + file_name;
425 strlcat(path, fileName, sizeof(path));
426 312
427 if (!WriteStringToFile(std::to_string(value), path)) { 313 if (!WriteStringToFile(std::to_string(value), path)) {
428 PLOG(ERROR) << "Failed to write '" << value << "' to " << path; 314 PLOG(ERROR) << "Failed to write '" << value << "' to " << path;
@@ -432,13 +318,13 @@ static bool setProcessGroupValue(uid_t uid, int pid, const char* fileName, int64
432} 318}
433 319
434bool setProcessGroupSwappiness(uid_t uid, int pid, int swappiness) { 320bool setProcessGroupSwappiness(uid_t uid, int pid, int swappiness) {
435 return setProcessGroupValue(uid, pid, "/memory.swappiness", swappiness); 321 return SetProcessGroupValue(uid, pid, "/memory.swappiness", swappiness);
436} 322}
437 323
438bool setProcessGroupSoftLimit(uid_t uid, int pid, int64_t soft_limit_in_bytes) { 324bool setProcessGroupSoftLimit(uid_t uid, int pid, int64_t soft_limit_in_bytes) {
439 return setProcessGroupValue(uid, pid, "/memory.soft_limit_in_bytes", soft_limit_in_bytes); 325 return SetProcessGroupValue(uid, pid, "/memory.soft_limit_in_bytes", soft_limit_in_bytes);
440} 326}
441 327
442bool setProcessGroupLimit(uid_t uid, int pid, int64_t limit_in_bytes) { 328bool setProcessGroupLimit(uid_t uid, int pid, int64_t limit_in_bytes) {
443 return setProcessGroupValue(uid, pid, "/memory.limit_in_bytes", limit_in_bytes); 329 return SetProcessGroupValue(uid, pid, "/memory.limit_in_bytes", limit_in_bytes);
444} 330}
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
index 1cfabd5be..83b0a7fcf 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -16,7 +16,11 @@
16 16
17cc_defaults { 17cc_defaults {
18 name: "libprocinfo_defaults", 18 name: "libprocinfo_defaults",
19 cflags: ["-Wall", "-Werror", "-Wextra"], 19 cflags: [
20 "-Wall",
21 "-Werror",
22 "-Wextra",
23 ],
20} 24}
21 25
22cc_library { 26cc_library {
@@ -65,7 +69,10 @@ cc_test {
65 }, 69 },
66 }, 70 },
67 71
68 shared_libs: ["libbase", "libprocinfo"], 72 shared_libs: [
73 "libbase",
74 "libprocinfo",
75 ],
69 76
70 compile_multilib: "both", 77 compile_multilib: "both",
71 multilib: { 78 multilib: {
diff --git a/libsystem/Android.bp b/libsystem/Android.bp
index 846a58526..82bf1bce0 100644
--- a/libsystem/Android.bp
+++ b/libsystem/Android.bp
@@ -11,5 +11,5 @@ cc_library_headers {
11 windows: { 11 windows: {
12 enabled: true, 12 enabled: true,
13 }, 13 },
14 } 14 },
15} 15}
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 34bfceff5..124c70e83 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -78,7 +78,10 @@ cc_library {
78 target: { 78 target: {
79 // Always disable optimizations for host to make it easier to debug. 79 // Always disable optimizations for host to make it easier to debug.
80 host: { 80 host: {
81 cflags: ["-O0", "-g"], 81 cflags: [
82 "-O0",
83 "-g",
84 ],
82 }, 85 },
83 vendor: { 86 vendor: {
84 cflags: ["-DNO_LIBDEXFILE_SUPPORT"], 87 cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
@@ -131,7 +134,10 @@ cc_library_static {
131 target: { 134 target: {
132 // Always disable optimizations for host to make it easier to debug. 135 // Always disable optimizations for host to make it easier to debug.
133 host: { 136 host: {
134 cflags: ["-O0", "-g"], 137 cflags: [
138 "-O0",
139 "-g",
140 ],
135 }, 141 },
136 }, 142 },
137 143
@@ -171,6 +177,7 @@ cc_test_library {
171 shared_libs: [ 177 shared_libs: [
172 "libbase", 178 "libbase",
173 "libunwindstack", 179 "libunwindstack",
180 "libdexfile",
174 ], 181 ],
175 182
176 // libdexfile will eventually properly export headers, for now include 183 // libdexfile will eventually properly export headers, for now include
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index c5f8138ed..430f6c580 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -77,7 +77,8 @@ void DexFiles::SetArch(ArchEnum arch) {
77 77
78uint64_t DexFiles::ReadEntryPtr32(uint64_t addr) { 78uint64_t DexFiles::ReadEntryPtr32(uint64_t addr) {
79 uint32_t entry; 79 uint32_t entry;
80 if (!memory_->ReadFully(addr, &entry, sizeof(entry))) { 80 const uint32_t field_offset = 12; // offset of first_entry_ in the descriptor struct.
81 if (!memory_->ReadFully(addr + field_offset, &entry, sizeof(entry))) {
81 return 0; 82 return 0;
82 } 83 }
83 return entry; 84 return entry;
@@ -85,7 +86,8 @@ uint64_t DexFiles::ReadEntryPtr32(uint64_t addr) {
85 86
86uint64_t DexFiles::ReadEntryPtr64(uint64_t addr) { 87uint64_t DexFiles::ReadEntryPtr64(uint64_t addr) {
87 uint64_t entry; 88 uint64_t entry;
88 if (!memory_->ReadFully(addr, &entry, sizeof(entry))) { 89 const uint32_t field_offset = 16; // offset of first_entry_ in the descriptor struct.
90 if (!memory_->ReadFully(addr + field_offset, &entry, sizeof(entry))) {
89 return 0; 91 return 0;
90 } 92 }
91 return entry; 93 return entry;
@@ -122,7 +124,7 @@ void DexFiles::Init(Maps* maps) {
122 initialized_ = true; 124 initialized_ = true;
123 entry_addr_ = 0; 125 entry_addr_ = 0;
124 126
125 const std::string dex_debug_name("__art_debug_dexfiles"); 127 const std::string dex_debug_name("__dex_debug_descriptor");
126 for (MapInfo* info : *maps) { 128 for (MapInfo* info : *maps) {
127 if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) { 129 if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
128 continue; 130 continue;
diff --git a/libunwindstack/DwarfOp.cpp b/libunwindstack/DwarfOp.cpp
index dcf04e6ff..5bc60b9d1 100644
--- a/libunwindstack/DwarfOp.cpp
+++ b/libunwindstack/DwarfOp.cpp
@@ -36,13 +36,45 @@ template <typename AddressType>
36constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256]; 36constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256];
37 37
38template <typename AddressType> 38template <typename AddressType>
39bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_version) { 39bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end) {
40 uint32_t iterations = 0;
41 is_register_ = false; 40 is_register_ = false;
42 stack_.clear(); 41 stack_.clear();
43 memory_->set_cur_offset(start); 42 memory_->set_cur_offset(start);
43 dex_pc_set_ = false;
44
45 // Unroll the first Decode calls to be able to check for a special
46 // sequence of ops and values that indicate this is the dex pc.
47 // The pattern is:
48 // OP_const4u (0x0c) 'D' 'E' 'X' '1'
49 // OP_drop (0x13)
50 if (memory_->cur_offset() < end) {
51 if (!Decode()) {
52 return false;
53 }
54 } else {
55 return true;
56 }
57 bool check_for_drop;
58 if (cur_op_ == 0x0c && operands_.back() == 0x31584544) {
59 check_for_drop = true;
60 } else {
61 check_for_drop = false;
62 }
63 if (memory_->cur_offset() < end) {
64 if (!Decode()) {
65 return false;
66 }
67 } else {
68 return true;
69 }
70
71 if (check_for_drop && cur_op_ == 0x13) {
72 dex_pc_set_ = true;
73 }
74
75 uint32_t iterations = 2;
44 while (memory_->cur_offset() < end) { 76 while (memory_->cur_offset() < end) {
45 if (!Decode(dwarf_version)) { 77 if (!Decode()) {
46 return false; 78 return false;
47 } 79 }
48 // To protect against a branch that creates an infinite loop, 80 // To protect against a branch that creates an infinite loop,
@@ -56,7 +88,7 @@ bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_vers
56} 88}
57 89
58template <typename AddressType> 90template <typename AddressType>
59bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) { 91bool DwarfOp<AddressType>::Decode() {
60 last_error_.code = DWARF_ERROR_NONE; 92 last_error_.code = DWARF_ERROR_NONE;
61 if (!memory_->ReadBytes(&cur_op_, 1)) { 93 if (!memory_->ReadBytes(&cur_op_, 1)) {
62 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 94 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
@@ -71,12 +103,6 @@ bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) {
71 return false; 103 return false;
72 } 104 }
73 105
74 // Check for an unsupported opcode.
75 if (dwarf_version < op->supported_version) {
76 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
77 return false;
78 }
79
80 // Make sure that the required number of stack elements is available. 106 // Make sure that the required number of stack elements is available.
81 if (stack_.size() < op->num_required_stack_values) { 107 if (stack_.size() < op->num_required_stack_values) {
82 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID; 108 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
@@ -434,22 +460,22 @@ bool DwarfOp<AddressType>::op_regx() {
434template <typename AddressType> 460template <typename AddressType>
435bool DwarfOp<AddressType>::op_breg() { 461bool DwarfOp<AddressType>::op_breg() {
436 uint16_t reg = cur_op() - 0x70; 462 uint16_t reg = cur_op() - 0x70;
437 if (reg >= regs_->total_regs()) { 463 if (reg >= regs_info_->Total()) {
438 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 464 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
439 return false; 465 return false;
440 } 466 }
441 stack_.push_front((*regs_)[reg] + OperandAt(0)); 467 stack_.push_front(regs_info_->Get(reg) + OperandAt(0));
442 return true; 468 return true;
443} 469}
444 470
445template <typename AddressType> 471template <typename AddressType>
446bool DwarfOp<AddressType>::op_bregx() { 472bool DwarfOp<AddressType>::op_bregx() {
447 AddressType reg = OperandAt(0); 473 AddressType reg = OperandAt(0);
448 if (reg >= regs_->total_regs()) { 474 if (reg >= regs_info_->Total()) {
449 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 475 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
450 return false; 476 return false;
451 } 477 }
452 stack_.push_front((*regs_)[reg] + OperandAt(1)); 478 stack_.push_front(regs_info_->Get(reg) + OperandAt(1));
453 return true; 479 return true;
454} 480}
455 481
diff --git a/libunwindstack/DwarfOp.h b/libunwindstack/DwarfOp.h
index 40b7b23b7..4c69b3d25 100644
--- a/libunwindstack/DwarfOp.h
+++ b/libunwindstack/DwarfOp.h
@@ -27,16 +27,10 @@
27#include <unwindstack/DwarfError.h> 27#include <unwindstack/DwarfError.h>
28 28
29#include "DwarfEncoding.h" 29#include "DwarfEncoding.h"
30#include "RegsInfo.h"
30 31
31namespace unwindstack { 32namespace unwindstack {
32 33
33enum DwarfVersion : uint8_t {
34 DWARF_VERSION_2 = 2,
35 DWARF_VERSION_3 = 3,
36 DWARF_VERSION_4 = 4,
37 DWARF_VERSION_MAX = DWARF_VERSION_4,
38};
39
40// Forward declarations. 34// Forward declarations.
41class DwarfMemory; 35class DwarfMemory;
42class Memory; 36class Memory;
@@ -51,7 +45,6 @@ class DwarfOp {
51 struct OpCallback { 45 struct OpCallback {
52 const char* name; 46 const char* name;
53 bool (DwarfOp::*handle_func)(); 47 bool (DwarfOp::*handle_func)();
54 uint8_t supported_version;
55 uint8_t num_required_stack_values; 48 uint8_t num_required_stack_values;
56 uint8_t num_operands; 49 uint8_t num_operands;
57 uint8_t operands[2]; 50 uint8_t operands[2];
@@ -62,21 +55,23 @@ class DwarfOp {
62 : memory_(memory), regular_memory_(regular_memory) {} 55 : memory_(memory), regular_memory_(regular_memory) {}
63 virtual ~DwarfOp() = default; 56 virtual ~DwarfOp() = default;
64 57
65 bool Decode(uint8_t dwarf_version); 58 bool Decode();
66 59
67 bool Eval(uint64_t start, uint64_t end, uint8_t dwarf_version); 60 bool Eval(uint64_t start, uint64_t end);
68 61
69 void GetLogInfo(uint64_t start, uint64_t end, std::vector<std::string>* lines); 62 void GetLogInfo(uint64_t start, uint64_t end, std::vector<std::string>* lines);
70 63
71 AddressType StackAt(size_t index) { return stack_[index]; } 64 AddressType StackAt(size_t index) { return stack_[index]; }
72 size_t StackSize() { return stack_.size(); } 65 size_t StackSize() { return stack_.size(); }
73 66
74 void set_regs(RegsImpl<AddressType>* regs) { regs_ = regs; } 67 void set_regs_info(RegsInfo<AddressType>* regs_info) { regs_info_ = regs_info; }
75 68
76 const DwarfErrorData& last_error() { return last_error_; } 69 const DwarfErrorData& last_error() { return last_error_; }
77 DwarfErrorCode LastErrorCode() { return last_error_.code; } 70 DwarfErrorCode LastErrorCode() { return last_error_.code; }
78 uint64_t LastErrorAddress() { return last_error_.address; } 71 uint64_t LastErrorAddress() { return last_error_.address; }
79 72
73 bool dex_pc_set() { return dex_pc_set_; }
74
80 bool is_register() { return is_register_; } 75 bool is_register() { return is_register_; }
81 76
82 uint8_t cur_op() { return cur_op_; } 77 uint8_t cur_op() { return cur_op_; }
@@ -97,7 +92,8 @@ class DwarfOp {
97 DwarfMemory* memory_; 92 DwarfMemory* memory_;
98 Memory* regular_memory_; 93 Memory* regular_memory_;
99 94
100 RegsImpl<AddressType>* regs_; 95 RegsInfo<AddressType>* regs_info_;
96 bool dex_pc_set_ = false;
101 bool is_register_ = false; 97 bool is_register_ = false;
102 DwarfErrorData last_error_{DWARF_ERROR_NONE, 0}; 98 DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
103 uint8_t cur_op_; 99 uint8_t cur_op_;
@@ -148,35 +144,32 @@ class DwarfOp {
148 bool op_not_implemented(); 144 bool op_not_implemented();
149 145
150 constexpr static OpCallback kCallbackTable[256] = { 146 constexpr static OpCallback kCallbackTable[256] = {
151 {nullptr, nullptr, 0, 0, 0, {}}, // 0x00 illegal op 147 {nullptr, nullptr, 0, 0, {}}, // 0x00 illegal op
152 {nullptr, nullptr, 0, 0, 0, {}}, // 0x01 illegal op 148 {nullptr, nullptr, 0, 0, {}}, // 0x01 illegal op
153 {nullptr, nullptr, 0, 0, 0, {}}, // 0x02 illegal op 149 {nullptr, nullptr, 0, 0, {}}, // 0x02 illegal op
154 { 150 {
155 // 0x03 DW_OP_addr 151 // 0x03 DW_OP_addr
156 "DW_OP_addr", 152 "DW_OP_addr",
157 &DwarfOp::op_push, 153 &DwarfOp::op_push,
158 DWARF_VERSION_2,
159 0, 154 0,
160 1, 155 1,
161 {DW_EH_PE_absptr}, 156 {DW_EH_PE_absptr},
162 }, 157 },
163 {nullptr, nullptr, 0, 0, 0, {}}, // 0x04 illegal op 158 {nullptr, nullptr, 0, 0, {}}, // 0x04 illegal op
164 {nullptr, nullptr, 0, 0, 0, {}}, // 0x05 illegal op 159 {nullptr, nullptr, 0, 0, {}}, // 0x05 illegal op
165 { 160 {
166 // 0x06 DW_OP_deref 161 // 0x06 DW_OP_deref
167 "DW_OP_deref", 162 "DW_OP_deref",
168 &DwarfOp::op_deref, 163 &DwarfOp::op_deref,
169 DWARF_VERSION_2,
170 1, 164 1,
171 0, 165 0,
172 {}, 166 {},
173 }, 167 },
174 {nullptr, nullptr, 0, 0, 0, {}}, // 0x07 illegal op 168 {nullptr, nullptr, 0, 0, {}}, // 0x07 illegal op
175 { 169 {
176 // 0x08 DW_OP_const1u 170 // 0x08 DW_OP_const1u
177 "DW_OP_const1u", 171 "DW_OP_const1u",
178 &DwarfOp::op_push, 172 &DwarfOp::op_push,
179 DWARF_VERSION_2,
180 0, 173 0,
181 1, 174 1,
182 {DW_EH_PE_udata1}, 175 {DW_EH_PE_udata1},
@@ -185,7 +178,6 @@ class DwarfOp {
185 // 0x09 DW_OP_const1s 178 // 0x09 DW_OP_const1s
186 "DW_OP_const1s", 179 "DW_OP_const1s",
187 &DwarfOp::op_push, 180 &DwarfOp::op_push,
188 DWARF_VERSION_2,
189 0, 181 0,
190 1, 182 1,
191 {DW_EH_PE_sdata1}, 183 {DW_EH_PE_sdata1},
@@ -194,7 +186,6 @@ class DwarfOp {
194 // 0x0a DW_OP_const2u 186 // 0x0a DW_OP_const2u
195 "DW_OP_const2u", 187 "DW_OP_const2u",
196 &DwarfOp::op_push, 188 &DwarfOp::op_push,
197 DWARF_VERSION_2,
198 0, 189 0,
199 1, 190 1,
200 {DW_EH_PE_udata2}, 191 {DW_EH_PE_udata2},
@@ -203,7 +194,6 @@ class DwarfOp {
203 // 0x0b DW_OP_const2s 194 // 0x0b DW_OP_const2s
204 "DW_OP_const2s", 195 "DW_OP_const2s",
205 &DwarfOp::op_push, 196 &DwarfOp::op_push,
206 DWARF_VERSION_2,
207 0, 197 0,
208 1, 198 1,
209 {DW_EH_PE_sdata2}, 199 {DW_EH_PE_sdata2},
@@ -212,7 +202,6 @@ class DwarfOp {
212 // 0x0c DW_OP_const4u 202 // 0x0c DW_OP_const4u
213 "DW_OP_const4u", 203 "DW_OP_const4u",
214 &DwarfOp::op_push, 204 &DwarfOp::op_push,
215 DWARF_VERSION_2,
216 0, 205 0,
217 1, 206 1,
218 {DW_EH_PE_udata4}, 207 {DW_EH_PE_udata4},
@@ -221,7 +210,6 @@ class DwarfOp {
221 // 0x0d DW_OP_const4s 210 // 0x0d DW_OP_const4s
222 "DW_OP_const4s", 211 "DW_OP_const4s",
223 &DwarfOp::op_push, 212 &DwarfOp::op_push,
224 DWARF_VERSION_2,
225 0, 213 0,
226 1, 214 1,
227 {DW_EH_PE_sdata4}, 215 {DW_EH_PE_sdata4},
@@ -230,7 +218,6 @@ class DwarfOp {
230 // 0x0e DW_OP_const8u 218 // 0x0e DW_OP_const8u
231 "DW_OP_const8u", 219 "DW_OP_const8u",
232 &DwarfOp::op_push, 220 &DwarfOp::op_push,
233 DWARF_VERSION_2,
234 0, 221 0,
235 1, 222 1,
236 {DW_EH_PE_udata8}, 223 {DW_EH_PE_udata8},
@@ -239,7 +226,6 @@ class DwarfOp {
239 // 0x0f DW_OP_const8s 226 // 0x0f DW_OP_const8s
240 "DW_OP_const8s", 227 "DW_OP_const8s",
241 &DwarfOp::op_push, 228 &DwarfOp::op_push,
242 DWARF_VERSION_2,
243 0, 229 0,
244 1, 230 1,
245 {DW_EH_PE_sdata8}, 231 {DW_EH_PE_sdata8},
@@ -248,7 +234,6 @@ class DwarfOp {
248 // 0x10 DW_OP_constu 234 // 0x10 DW_OP_constu
249 "DW_OP_constu", 235 "DW_OP_constu",
250 &DwarfOp::op_push, 236 &DwarfOp::op_push,
251 DWARF_VERSION_2,
252 0, 237 0,
253 1, 238 1,
254 {DW_EH_PE_uleb128}, 239 {DW_EH_PE_uleb128},
@@ -257,7 +242,6 @@ class DwarfOp {
257 // 0x11 DW_OP_consts 242 // 0x11 DW_OP_consts
258 "DW_OP_consts", 243 "DW_OP_consts",
259 &DwarfOp::op_push, 244 &DwarfOp::op_push,
260 DWARF_VERSION_2,
261 0, 245 0,
262 1, 246 1,
263 {DW_EH_PE_sleb128}, 247 {DW_EH_PE_sleb128},
@@ -266,7 +250,6 @@ class DwarfOp {
266 // 0x12 DW_OP_dup 250 // 0x12 DW_OP_dup
267 "DW_OP_dup", 251 "DW_OP_dup",
268 &DwarfOp::op_dup, 252 &DwarfOp::op_dup,
269 DWARF_VERSION_2,
270 1, 253 1,
271 0, 254 0,
272 {}, 255 {},
@@ -275,7 +258,6 @@ class DwarfOp {
275 // 0x13 DW_OP_drop 258 // 0x13 DW_OP_drop
276 "DW_OP_drop", 259 "DW_OP_drop",
277 &DwarfOp::op_drop, 260 &DwarfOp::op_drop,
278 DWARF_VERSION_2,
279 1, 261 1,
280 0, 262 0,
281 {}, 263 {},
@@ -284,7 +266,6 @@ class DwarfOp {
284 // 0x14 DW_OP_over 266 // 0x14 DW_OP_over
285 "DW_OP_over", 267 "DW_OP_over",
286 &DwarfOp::op_over, 268 &DwarfOp::op_over,
287 DWARF_VERSION_2,
288 2, 269 2,
289 0, 270 0,
290 {}, 271 {},
@@ -293,7 +274,6 @@ class DwarfOp {
293 // 0x15 DW_OP_pick 274 // 0x15 DW_OP_pick
294 "DW_OP_pick", 275 "DW_OP_pick",
295 &DwarfOp::op_pick, 276 &DwarfOp::op_pick,
296 DWARF_VERSION_2,
297 0, 277 0,
298 1, 278 1,
299 {DW_EH_PE_udata1}, 279 {DW_EH_PE_udata1},
@@ -302,7 +282,6 @@ class DwarfOp {
302 // 0x16 DW_OP_swap 282 // 0x16 DW_OP_swap
303 "DW_OP_swap", 283 "DW_OP_swap",
304 &DwarfOp::op_swap, 284 &DwarfOp::op_swap,
305 DWARF_VERSION_2,
306 2, 285 2,
307 0, 286 0,
308 {}, 287 {},
@@ -311,7 +290,6 @@ class DwarfOp {
311 // 0x17 DW_OP_rot 290 // 0x17 DW_OP_rot
312 "DW_OP_rot", 291 "DW_OP_rot",
313 &DwarfOp::op_rot, 292 &DwarfOp::op_rot,
314 DWARF_VERSION_2,
315 3, 293 3,
316 0, 294 0,
317 {}, 295 {},
@@ -320,7 +298,6 @@ class DwarfOp {
320 // 0x18 DW_OP_xderef 298 // 0x18 DW_OP_xderef
321 "DW_OP_xderef", 299 "DW_OP_xderef",
322 &DwarfOp::op_not_implemented, 300 &DwarfOp::op_not_implemented,
323 DWARF_VERSION_2,
324 2, 301 2,
325 0, 302 0,
326 {}, 303 {},
@@ -329,7 +306,6 @@ class DwarfOp {
329 // 0x19 DW_OP_abs 306 // 0x19 DW_OP_abs
330 "DW_OP_abs", 307 "DW_OP_abs",
331 &DwarfOp::op_abs, 308 &DwarfOp::op_abs,
332 DWARF_VERSION_2,
333 1, 309 1,
334 0, 310 0,
335 {}, 311 {},
@@ -338,7 +314,6 @@ class DwarfOp {
338 // 0x1a DW_OP_and 314 // 0x1a DW_OP_and
339 "DW_OP_and", 315 "DW_OP_and",
340 &DwarfOp::op_and, 316 &DwarfOp::op_and,
341 DWARF_VERSION_2,
342 2, 317 2,
343 0, 318 0,
344 {}, 319 {},
@@ -347,7 +322,6 @@ class DwarfOp {
347 // 0x1b DW_OP_div 322 // 0x1b DW_OP_div
348 "DW_OP_div", 323 "DW_OP_div",
349 &DwarfOp::op_div, 324 &DwarfOp::op_div,
350 DWARF_VERSION_2,
351 2, 325 2,
352 0, 326 0,
353 {}, 327 {},
@@ -356,7 +330,6 @@ class DwarfOp {
356 // 0x1c DW_OP_minus 330 // 0x1c DW_OP_minus
357 "DW_OP_minus", 331 "DW_OP_minus",
358 &DwarfOp::op_minus, 332 &DwarfOp::op_minus,
359 DWARF_VERSION_2,
360 2, 333 2,
361 0, 334 0,
362 {}, 335 {},
@@ -365,7 +338,6 @@ class DwarfOp {
365 // 0x1d DW_OP_mod 338 // 0x1d DW_OP_mod
366 "DW_OP_mod", 339 "DW_OP_mod",
367 &DwarfOp::op_mod, 340 &DwarfOp::op_mod,
368 DWARF_VERSION_2,
369 2, 341 2,
370 0, 342 0,
371 {}, 343 {},
@@ -374,7 +346,6 @@ class DwarfOp {
374 // 0x1e DW_OP_mul 346 // 0x1e DW_OP_mul
375 "DW_OP_mul", 347 "DW_OP_mul",
376 &DwarfOp::op_mul, 348 &DwarfOp::op_mul,
377 DWARF_VERSION_2,
378 2, 349 2,
379 0, 350 0,
380 {}, 351 {},
@@ -383,7 +354,6 @@ class DwarfOp {
383 // 0x1f DW_OP_neg 354 // 0x1f DW_OP_neg
384 "DW_OP_neg", 355 "DW_OP_neg",
385 &DwarfOp::op_neg, 356 &DwarfOp::op_neg,
386 DWARF_VERSION_2,
387 1, 357 1,
388 0, 358 0,
389 {}, 359 {},
@@ -392,7 +362,6 @@ class DwarfOp {
392 // 0x20 DW_OP_not 362 // 0x20 DW_OP_not
393 "DW_OP_not", 363 "DW_OP_not",
394 &DwarfOp::op_not, 364 &DwarfOp::op_not,
395 DWARF_VERSION_2,
396 1, 365 1,
397 0, 366 0,
398 {}, 367 {},
@@ -401,7 +370,6 @@ class DwarfOp {
401 // 0x21 DW_OP_or 370 // 0x21 DW_OP_or
402 "DW_OP_or", 371 "DW_OP_or",
403 &DwarfOp::op_or, 372 &DwarfOp::op_or,
404 DWARF_VERSION_2,
405 2, 373 2,
406 0, 374 0,
407 {}, 375 {},
@@ -410,7 +378,6 @@ class DwarfOp {
410 // 0x22 DW_OP_plus 378 // 0x22 DW_OP_plus
411 "DW_OP_plus", 379 "DW_OP_plus",
412 &DwarfOp::op_plus, 380 &DwarfOp::op_plus,
413 DWARF_VERSION_2,
414 2, 381 2,
415 0, 382 0,
416 {}, 383 {},
@@ -419,7 +386,6 @@ class DwarfOp {
419 // 0x23 DW_OP_plus_uconst 386 // 0x23 DW_OP_plus_uconst
420 "DW_OP_plus_uconst", 387 "DW_OP_plus_uconst",
421 &DwarfOp::op_plus_uconst, 388 &DwarfOp::op_plus_uconst,
422 DWARF_VERSION_2,
423 1, 389 1,
424 1, 390 1,
425 {DW_EH_PE_uleb128}, 391 {DW_EH_PE_uleb128},
@@ -428,7 +394,6 @@ class DwarfOp {
428 // 0x24 DW_OP_shl 394 // 0x24 DW_OP_shl
429 "DW_OP_shl", 395 "DW_OP_shl",
430 &DwarfOp::op_shl, 396 &DwarfOp::op_shl,
431 DWARF_VERSION_2,
432 2, 397 2,
433 0, 398 0,
434 {}, 399 {},
@@ -437,7 +402,6 @@ class DwarfOp {
437 // 0x25 DW_OP_shr 402 // 0x25 DW_OP_shr
438 "DW_OP_shr", 403 "DW_OP_shr",
439 &DwarfOp::op_shr, 404 &DwarfOp::op_shr,
440 DWARF_VERSION_2,
441 2, 405 2,
442 0, 406 0,
443 {}, 407 {},
@@ -446,7 +410,6 @@ class DwarfOp {
446 // 0x26 DW_OP_shra 410 // 0x26 DW_OP_shra
447 "DW_OP_shra", 411 "DW_OP_shra",
448 &DwarfOp::op_shra, 412 &DwarfOp::op_shra,
449 DWARF_VERSION_2,
450 2, 413 2,
451 0, 414 0,
452 {}, 415 {},
@@ -455,7 +418,6 @@ class DwarfOp {
455 // 0x27 DW_OP_xor 418 // 0x27 DW_OP_xor
456 "DW_OP_xor", 419 "DW_OP_xor",
457 &DwarfOp::op_xor, 420 &DwarfOp::op_xor,
458 DWARF_VERSION_2,
459 2, 421 2,
460 0, 422 0,
461 {}, 423 {},
@@ -464,7 +426,6 @@ class DwarfOp {
464 // 0x28 DW_OP_bra 426 // 0x28 DW_OP_bra
465 "DW_OP_bra", 427 "DW_OP_bra",
466 &DwarfOp::op_bra, 428 &DwarfOp::op_bra,
467 DWARF_VERSION_2,
468 1, 429 1,
469 1, 430 1,
470 {DW_EH_PE_sdata2}, 431 {DW_EH_PE_sdata2},
@@ -473,7 +434,6 @@ class DwarfOp {
473 // 0x29 DW_OP_eq 434 // 0x29 DW_OP_eq
474 "DW_OP_eq", 435 "DW_OP_eq",
475 &DwarfOp::op_eq, 436 &DwarfOp::op_eq,
476 DWARF_VERSION_2,
477 2, 437 2,
478 0, 438 0,
479 {}, 439 {},
@@ -482,7 +442,6 @@ class DwarfOp {
482 // 0x2a DW_OP_ge 442 // 0x2a DW_OP_ge
483 "DW_OP_ge", 443 "DW_OP_ge",
484 &DwarfOp::op_ge, 444 &DwarfOp::op_ge,
485 DWARF_VERSION_2,
486 2, 445 2,
487 0, 446 0,
488 {}, 447 {},
@@ -491,7 +450,6 @@ class DwarfOp {
491 // 0x2b DW_OP_gt 450 // 0x2b DW_OP_gt
492 "DW_OP_gt", 451 "DW_OP_gt",
493 &DwarfOp::op_gt, 452 &DwarfOp::op_gt,
494 DWARF_VERSION_2,
495 2, 453 2,
496 0, 454 0,
497 {}, 455 {},
@@ -500,7 +458,6 @@ class DwarfOp {
500 // 0x2c DW_OP_le 458 // 0x2c DW_OP_le
501 "DW_OP_le", 459 "DW_OP_le",
502 &DwarfOp::op_le, 460 &DwarfOp::op_le,
503 DWARF_VERSION_2,
504 2, 461 2,
505 0, 462 0,
506 {}, 463 {},
@@ -509,7 +466,6 @@ class DwarfOp {
509 // 0x2d DW_OP_lt 466 // 0x2d DW_OP_lt
510 "DW_OP_lt", 467 "DW_OP_lt",
511 &DwarfOp::op_lt, 468 &DwarfOp::op_lt,
512 DWARF_VERSION_2,
513 2, 469 2,
514 0, 470 0,
515 {}, 471 {},
@@ -518,7 +474,6 @@ class DwarfOp {
518 // 0x2e DW_OP_ne 474 // 0x2e DW_OP_ne
519 "DW_OP_ne", 475 "DW_OP_ne",
520 &DwarfOp::op_ne, 476 &DwarfOp::op_ne,
521 DWARF_VERSION_2,
522 2, 477 2,
523 0, 478 0,
524 {}, 479 {},
@@ -527,7 +482,6 @@ class DwarfOp {
527 // 0x2f DW_OP_skip 482 // 0x2f DW_OP_skip
528 "DW_OP_skip", 483 "DW_OP_skip",
529 &DwarfOp::op_skip, 484 &DwarfOp::op_skip,
530 DWARF_VERSION_2,
531 0, 485 0,
532 1, 486 1,
533 {DW_EH_PE_sdata2}, 487 {DW_EH_PE_sdata2},
@@ -536,7 +490,6 @@ class DwarfOp {
536 // 0x30 DW_OP_lit0 490 // 0x30 DW_OP_lit0
537 "DW_OP_lit0", 491 "DW_OP_lit0",
538 &DwarfOp::op_lit, 492 &DwarfOp::op_lit,
539 DWARF_VERSION_2,
540 0, 493 0,
541 0, 494 0,
542 {}, 495 {},
@@ -545,7 +498,6 @@ class DwarfOp {
545 // 0x31 DW_OP_lit1 498 // 0x31 DW_OP_lit1
546 "DW_OP_lit1", 499 "DW_OP_lit1",
547 &DwarfOp::op_lit, 500 &DwarfOp::op_lit,
548 DWARF_VERSION_2,
549 0, 501 0,
550 0, 502 0,
551 {}, 503 {},
@@ -554,7 +506,6 @@ class DwarfOp {
554 // 0x32 DW_OP_lit2 506 // 0x32 DW_OP_lit2
555 "DW_OP_lit2", 507 "DW_OP_lit2",
556 &DwarfOp::op_lit, 508 &DwarfOp::op_lit,
557 DWARF_VERSION_2,
558 0, 509 0,
559 0, 510 0,
560 {}, 511 {},
@@ -563,7 +514,6 @@ class DwarfOp {
563 // 0x33 DW_OP_lit3 514 // 0x33 DW_OP_lit3
564 "DW_OP_lit3", 515 "DW_OP_lit3",
565 &DwarfOp::op_lit, 516 &DwarfOp::op_lit,
566 DWARF_VERSION_2,
567 0, 517 0,
568 0, 518 0,
569 {}, 519 {},
@@ -572,7 +522,6 @@ class DwarfOp {
572 // 0x34 DW_OP_lit4 522 // 0x34 DW_OP_lit4
573 "DW_OP_lit4", 523 "DW_OP_lit4",
574 &DwarfOp::op_lit, 524 &DwarfOp::op_lit,
575 DWARF_VERSION_2,
576 0, 525 0,
577 0, 526 0,
578 {}, 527 {},
@@ -581,7 +530,6 @@ class DwarfOp {
581 // 0x35 DW_OP_lit5 530 // 0x35 DW_OP_lit5
582 "DW_OP_lit5", 531 "DW_OP_lit5",
583 &DwarfOp::op_lit, 532 &DwarfOp::op_lit,
584 DWARF_VERSION_2,
585 0, 533 0,
586 0, 534 0,
587 {}, 535 {},
@@ -590,7 +538,6 @@ class DwarfOp {
590 // 0x36 DW_OP_lit6 538 // 0x36 DW_OP_lit6
591 "DW_OP_lit6", 539 "DW_OP_lit6",
592 &DwarfOp::op_lit, 540 &DwarfOp::op_lit,
593 DWARF_VERSION_2,
594 0, 541 0,
595 0, 542 0,
596 {}, 543 {},
@@ -599,7 +546,6 @@ class DwarfOp {
599 // 0x37 DW_OP_lit7 546 // 0x37 DW_OP_lit7
600 "DW_OP_lit7", 547 "DW_OP_lit7",
601 &DwarfOp::op_lit, 548 &DwarfOp::op_lit,
602 DWARF_VERSION_2,
603 0, 549 0,
604 0, 550 0,
605 {}, 551 {},
@@ -608,7 +554,6 @@ class DwarfOp {
608 // 0x38 DW_OP_lit8 554 // 0x38 DW_OP_lit8
609 "DW_OP_lit8", 555 "DW_OP_lit8",
610 &DwarfOp::op_lit, 556 &DwarfOp::op_lit,
611 DWARF_VERSION_2,
612 0, 557 0,
613 0, 558 0,
614 {}, 559 {},
@@ -617,7 +562,6 @@ class DwarfOp {
617 // 0x39 DW_OP_lit9 562 // 0x39 DW_OP_lit9
618 "DW_OP_lit9", 563 "DW_OP_lit9",
619 &DwarfOp::op_lit, 564 &DwarfOp::op_lit,
620 DWARF_VERSION_2,
621 0, 565 0,
622 0, 566 0,
623 {}, 567 {},
@@ -626,7 +570,6 @@ class DwarfOp {
626 // 0x3a DW_OP_lit10 570 // 0x3a DW_OP_lit10
627 "DW_OP_lit10", 571 "DW_OP_lit10",
628 &DwarfOp::op_lit, 572 &DwarfOp::op_lit,
629 DWARF_VERSION_2,
630 0, 573 0,
631 0, 574 0,
632 {}, 575 {},
@@ -635,7 +578,6 @@ class DwarfOp {
635 // 0x3b DW_OP_lit11 578 // 0x3b DW_OP_lit11
636 "DW_OP_lit11", 579 "DW_OP_lit11",
637 &DwarfOp::op_lit, 580 &DwarfOp::op_lit,
638 DWARF_VERSION_2,
639 0, 581 0,
640 0, 582 0,
641 {}, 583 {},
@@ -644,7 +586,6 @@ class DwarfOp {
644 // 0x3c DW_OP_lit12 586 // 0x3c DW_OP_lit12
645 "DW_OP_lit12", 587 "DW_OP_lit12",
646 &DwarfOp::op_lit, 588 &DwarfOp::op_lit,
647 DWARF_VERSION_2,
648 0, 589 0,
649 0, 590 0,
650 {}, 591 {},
@@ -653,7 +594,6 @@ class DwarfOp {
653 // 0x3d DW_OP_lit13 594 // 0x3d DW_OP_lit13
654 "DW_OP_lit13", 595 "DW_OP_lit13",
655 &DwarfOp::op_lit, 596 &DwarfOp::op_lit,
656 DWARF_VERSION_2,
657 0, 597 0,
658 0, 598 0,
659 {}, 599 {},
@@ -662,7 +602,6 @@ class DwarfOp {
662 // 0x3e DW_OP_lit14 602 // 0x3e DW_OP_lit14
663 "DW_OP_lit14", 603 "DW_OP_lit14",
664 &DwarfOp::op_lit, 604 &DwarfOp::op_lit,
665 DWARF_VERSION_2,
666 0, 605 0,
667 0, 606 0,
668 {}, 607 {},
@@ -671,7 +610,6 @@ class DwarfOp {
671 // 0x3f DW_OP_lit15 610 // 0x3f DW_OP_lit15
672 "DW_OP_lit15", 611 "DW_OP_lit15",
673 &DwarfOp::op_lit, 612 &DwarfOp::op_lit,
674 DWARF_VERSION_2,
675 0, 613 0,
676 0, 614 0,
677 {}, 615 {},
@@ -680,7 +618,6 @@ class DwarfOp {
680 // 0x40 DW_OP_lit16 618 // 0x40 DW_OP_lit16
681 "DW_OP_lit16", 619 "DW_OP_lit16",
682 &DwarfOp::op_lit, 620 &DwarfOp::op_lit,
683 DWARF_VERSION_2,
684 0, 621 0,
685 0, 622 0,
686 {}, 623 {},
@@ -689,7 +626,6 @@ class DwarfOp {
689 // 0x41 DW_OP_lit17 626 // 0x41 DW_OP_lit17
690 "DW_OP_lit17", 627 "DW_OP_lit17",
691 &DwarfOp::op_lit, 628 &DwarfOp::op_lit,
692 DWARF_VERSION_2,
693 0, 629 0,
694 0, 630 0,
695 {}, 631 {},
@@ -698,7 +634,6 @@ class DwarfOp {
698 // 0x42 DW_OP_lit18 634 // 0x42 DW_OP_lit18
699 "DW_OP_lit18", 635 "DW_OP_lit18",
700 &DwarfOp::op_lit, 636 &DwarfOp::op_lit,
701 DWARF_VERSION_2,
702 0, 637 0,
703 0, 638 0,
704 {}, 639 {},
@@ -707,7 +642,6 @@ class DwarfOp {
707 // 0x43 DW_OP_lit19 642 // 0x43 DW_OP_lit19
708 "DW_OP_lit19", 643 "DW_OP_lit19",
709 &DwarfOp::op_lit, 644 &DwarfOp::op_lit,
710 DWARF_VERSION_2,
711 0, 645 0,
712 0, 646 0,
713 {}, 647 {},
@@ -716,7 +650,6 @@ class DwarfOp {
716 // 0x44 DW_OP_lit20 650 // 0x44 DW_OP_lit20
717 "DW_OP_lit20", 651 "DW_OP_lit20",
718 &DwarfOp::op_lit, 652 &DwarfOp::op_lit,
719 DWARF_VERSION_2,
720 0, 653 0,
721 0, 654 0,
722 {}, 655 {},
@@ -725,7 +658,6 @@ class DwarfOp {
725 // 0x45 DW_OP_lit21 658 // 0x45 DW_OP_lit21
726 "DW_OP_lit21", 659 "DW_OP_lit21",
727 &DwarfOp::op_lit, 660 &DwarfOp::op_lit,
728 DWARF_VERSION_2,
729 0, 661 0,
730 0, 662 0,
731 {}, 663 {},
@@ -734,7 +666,6 @@ class DwarfOp {
734 // 0x46 DW_OP_lit22 666 // 0x46 DW_OP_lit22
735 "DW_OP_lit22", 667 "DW_OP_lit22",
736 &DwarfOp::op_lit, 668 &DwarfOp::op_lit,
737 DWARF_VERSION_2,
738 0, 669 0,
739 0, 670 0,
740 {}, 671 {},
@@ -743,7 +674,6 @@ class DwarfOp {
743 // 0x47 DW_OP_lit23 674 // 0x47 DW_OP_lit23
744 "DW_OP_lit23", 675 "DW_OP_lit23",
745 &DwarfOp::op_lit, 676 &DwarfOp::op_lit,
746 DWARF_VERSION_2,
747 0, 677 0,
748 0, 678 0,
749 {}, 679 {},
@@ -752,7 +682,6 @@ class DwarfOp {
752 // 0x48 DW_OP_lit24 682 // 0x48 DW_OP_lit24
753 "DW_OP_lit24", 683 "DW_OP_lit24",
754 &DwarfOp::op_lit, 684 &DwarfOp::op_lit,
755 DWARF_VERSION_2,
756 0, 685 0,
757 0, 686 0,
758 {}, 687 {},
@@ -761,7 +690,6 @@ class DwarfOp {
761 // 0x49 DW_OP_lit25 690 // 0x49 DW_OP_lit25
762 "DW_OP_lit25", 691 "DW_OP_lit25",
763 &DwarfOp::op_lit, 692 &DwarfOp::op_lit,
764 DWARF_VERSION_2,
765 0, 693 0,
766 0, 694 0,
767 {}, 695 {},
@@ -770,7 +698,6 @@ class DwarfOp {
770 // 0x4a DW_OP_lit26 698 // 0x4a DW_OP_lit26
771 "DW_OP_lit26", 699 "DW_OP_lit26",
772 &DwarfOp::op_lit, 700 &DwarfOp::op_lit,
773 DWARF_VERSION_2,
774 0, 701 0,
775 0, 702 0,
776 {}, 703 {},
@@ -779,7 +706,6 @@ class DwarfOp {
779 // 0x4b DW_OP_lit27 706 // 0x4b DW_OP_lit27
780 "DW_OP_lit27", 707 "DW_OP_lit27",
781 &DwarfOp::op_lit, 708 &DwarfOp::op_lit,
782 DWARF_VERSION_2,
783 0, 709 0,
784 0, 710 0,
785 {}, 711 {},
@@ -788,7 +714,6 @@ class DwarfOp {
788 // 0x4c DW_OP_lit28 714 // 0x4c DW_OP_lit28
789 "DW_OP_lit28", 715 "DW_OP_lit28",
790 &DwarfOp::op_lit, 716 &DwarfOp::op_lit,
791 DWARF_VERSION_2,
792 0, 717 0,
793 0, 718 0,
794 {}, 719 {},
@@ -797,7 +722,6 @@ class DwarfOp {
797 // 0x4d DW_OP_lit29 722 // 0x4d DW_OP_lit29
798 "DW_OP_lit29", 723 "DW_OP_lit29",
799 &DwarfOp::op_lit, 724 &DwarfOp::op_lit,
800 DWARF_VERSION_2,
801 0, 725 0,
802 0, 726 0,
803 {}, 727 {},
@@ -806,7 +730,6 @@ class DwarfOp {
806 // 0x4e DW_OP_lit30 730 // 0x4e DW_OP_lit30
807 "DW_OP_lit30", 731 "DW_OP_lit30",
808 &DwarfOp::op_lit, 732 &DwarfOp::op_lit,
809 DWARF_VERSION_2,
810 0, 733 0,
811 0, 734 0,
812 {}, 735 {},
@@ -815,7 +738,6 @@ class DwarfOp {
815 // 0x4f DW_OP_lit31 738 // 0x4f DW_OP_lit31
816 "DW_OP_lit31", 739 "DW_OP_lit31",
817 &DwarfOp::op_lit, 740 &DwarfOp::op_lit,
818 DWARF_VERSION_2,
819 0, 741 0,
820 0, 742 0,
821 {}, 743 {},
@@ -824,7 +746,6 @@ class DwarfOp {
824 // 0x50 DW_OP_reg0 746 // 0x50 DW_OP_reg0
825 "DW_OP_reg0", 747 "DW_OP_reg0",
826 &DwarfOp::op_reg, 748 &DwarfOp::op_reg,
827 DWARF_VERSION_2,
828 0, 749 0,
829 0, 750 0,
830 {}, 751 {},
@@ -833,7 +754,6 @@ class DwarfOp {
833 // 0x51 DW_OP_reg1 754 // 0x51 DW_OP_reg1
834 "DW_OP_reg1", 755 "DW_OP_reg1",
835 &DwarfOp::op_reg, 756 &DwarfOp::op_reg,
836 DWARF_VERSION_2,
837 0, 757 0,
838 0, 758 0,
839 {}, 759 {},
@@ -842,7 +762,6 @@ class DwarfOp {
842 // 0x52 DW_OP_reg2 762 // 0x52 DW_OP_reg2
843 "DW_OP_reg2", 763 "DW_OP_reg2",
844 &DwarfOp::op_reg, 764 &DwarfOp::op_reg,
845 DWARF_VERSION_2,
846 0, 765 0,
847 0, 766 0,
848 {}, 767 {},
@@ -851,7 +770,6 @@ class DwarfOp {
851 // 0x53 DW_OP_reg3 770 // 0x53 DW_OP_reg3
852 "DW_OP_reg3", 771 "DW_OP_reg3",
853 &DwarfOp::op_reg, 772 &DwarfOp::op_reg,
854 DWARF_VERSION_2,
855 0, 773 0,
856 0, 774 0,
857 {}, 775 {},
@@ -860,7 +778,6 @@ class DwarfOp {
860 // 0x54 DW_OP_reg4 778 // 0x54 DW_OP_reg4
861 "DW_OP_reg4", 779 "DW_OP_reg4",
862 &DwarfOp::op_reg, 780 &DwarfOp::op_reg,
863 DWARF_VERSION_2,
864 0, 781 0,
865 0, 782 0,
866 {}, 783 {},
@@ -869,7 +786,6 @@ class DwarfOp {
869 // 0x55 DW_OP_reg5 786 // 0x55 DW_OP_reg5
870 "DW_OP_reg5", 787 "DW_OP_reg5",
871 &DwarfOp::op_reg, 788 &DwarfOp::op_reg,
872 DWARF_VERSION_2,
873 0, 789 0,
874 0, 790 0,
875 {}, 791 {},
@@ -878,7 +794,6 @@ class DwarfOp {
878 // 0x56 DW_OP_reg6 794 // 0x56 DW_OP_reg6
879 "DW_OP_reg6", 795 "DW_OP_reg6",
880 &DwarfOp::op_reg, 796 &DwarfOp::op_reg,
881 DWARF_VERSION_2,
882 0, 797 0,
883 0, 798 0,
884 {}, 799 {},
@@ -887,7 +802,6 @@ class DwarfOp {
887 // 0x57 DW_OP_reg7 802 // 0x57 DW_OP_reg7
888 "DW_OP_reg7", 803 "DW_OP_reg7",
889 &DwarfOp::op_reg, 804 &DwarfOp::op_reg,
890 DWARF_VERSION_2,
891 0, 805 0,
892 0, 806 0,
893 {}, 807 {},
@@ -896,7 +810,6 @@ class DwarfOp {
896 // 0x58 DW_OP_reg8 810 // 0x58 DW_OP_reg8
897 "DW_OP_reg8", 811 "DW_OP_reg8",
898 &DwarfOp::op_reg, 812 &DwarfOp::op_reg,
899 DWARF_VERSION_2,
900 0, 813 0,
901 0, 814 0,
902 {}, 815 {},
@@ -905,7 +818,6 @@ class DwarfOp {
905 // 0x59 DW_OP_reg9 818 // 0x59 DW_OP_reg9
906 "DW_OP_reg9", 819 "DW_OP_reg9",
907 &DwarfOp::op_reg, 820 &DwarfOp::op_reg,
908 DWARF_VERSION_2,
909 0, 821 0,
910 0, 822 0,
911 {}, 823 {},
@@ -914,7 +826,6 @@ class DwarfOp {
914 // 0x5a DW_OP_reg10 826 // 0x5a DW_OP_reg10
915 "DW_OP_reg10", 827 "DW_OP_reg10",
916 &DwarfOp::op_reg, 828 &DwarfOp::op_reg,
917 DWARF_VERSION_2,
918 0, 829 0,
919 0, 830 0,
920 {}, 831 {},
@@ -923,7 +834,6 @@ class DwarfOp {
923 // 0x5b DW_OP_reg11 834 // 0x5b DW_OP_reg11
924 "DW_OP_reg11", 835 "DW_OP_reg11",
925 &DwarfOp::op_reg, 836 &DwarfOp::op_reg,
926 DWARF_VERSION_2,
927 0, 837 0,
928 0, 838 0,
929 {}, 839 {},
@@ -932,7 +842,6 @@ class DwarfOp {
932 // 0x5c DW_OP_reg12 842 // 0x5c DW_OP_reg12
933 "DW_OP_reg12", 843 "DW_OP_reg12",
934 &DwarfOp::op_reg, 844 &DwarfOp::op_reg,
935 DWARF_VERSION_2,
936 0, 845 0,
937 0, 846 0,
938 {}, 847 {},
@@ -941,7 +850,6 @@ class DwarfOp {
941 // 0x5d DW_OP_reg13 850 // 0x5d DW_OP_reg13
942 "DW_OP_reg13", 851 "DW_OP_reg13",
943 &DwarfOp::op_reg, 852 &DwarfOp::op_reg,
944 DWARF_VERSION_2,
945 0, 853 0,
946 0, 854 0,
947 {}, 855 {},
@@ -950,7 +858,6 @@ class DwarfOp {
950 // 0x5e DW_OP_reg14 858 // 0x5e DW_OP_reg14
951 "DW_OP_reg14", 859 "DW_OP_reg14",
952 &DwarfOp::op_reg, 860 &DwarfOp::op_reg,
953 DWARF_VERSION_2,
954 0, 861 0,
955 0, 862 0,
956 {}, 863 {},
@@ -959,7 +866,6 @@ class DwarfOp {
959 // 0x5f DW_OP_reg15 866 // 0x5f DW_OP_reg15
960 "DW_OP_reg15", 867 "DW_OP_reg15",
961 &DwarfOp::op_reg, 868 &DwarfOp::op_reg,
962 DWARF_VERSION_2,
963 0, 869 0,
964 0, 870 0,
965 {}, 871 {},
@@ -968,7 +874,6 @@ class DwarfOp {
968 // 0x60 DW_OP_reg16 874 // 0x60 DW_OP_reg16
969 "DW_OP_reg16", 875 "DW_OP_reg16",
970 &DwarfOp::op_reg, 876 &DwarfOp::op_reg,
971 DWARF_VERSION_2,
972 0, 877 0,
973 0, 878 0,
974 {}, 879 {},
@@ -977,7 +882,6 @@ class DwarfOp {
977 // 0x61 DW_OP_reg17 882 // 0x61 DW_OP_reg17
978 "DW_OP_reg17", 883 "DW_OP_reg17",
979 &DwarfOp::op_reg, 884 &DwarfOp::op_reg,
980 DWARF_VERSION_2,
981 0, 885 0,
982 0, 886 0,
983 {}, 887 {},
@@ -986,7 +890,6 @@ class DwarfOp {
986 // 0x62 DW_OP_reg18 890 // 0x62 DW_OP_reg18
987 "DW_OP_reg18", 891 "DW_OP_reg18",
988 &DwarfOp::op_reg, 892 &DwarfOp::op_reg,
989 DWARF_VERSION_2,
990 0, 893 0,
991 0, 894 0,
992 {}, 895 {},
@@ -995,7 +898,6 @@ class DwarfOp {
995 // 0x63 DW_OP_reg19 898 // 0x63 DW_OP_reg19
996 "DW_OP_reg19", 899 "DW_OP_reg19",
997 &DwarfOp::op_reg, 900 &DwarfOp::op_reg,
998 DWARF_VERSION_2,
999 0, 901 0,
1000 0, 902 0,
1001 {}, 903 {},
@@ -1004,7 +906,6 @@ class DwarfOp {
1004 // 0x64 DW_OP_reg20 906 // 0x64 DW_OP_reg20
1005 "DW_OP_reg20", 907 "DW_OP_reg20",
1006 &DwarfOp::op_reg, 908 &DwarfOp::op_reg,
1007 DWARF_VERSION_2,
1008 0, 909 0,
1009 0, 910 0,
1010 {}, 911 {},
@@ -1013,7 +914,6 @@ class DwarfOp {
1013 // 0x65 DW_OP_reg21 914 // 0x65 DW_OP_reg21
1014 "DW_OP_reg21", 915 "DW_OP_reg21",
1015 &DwarfOp::op_reg, 916 &DwarfOp::op_reg,
1016 DWARF_VERSION_2,
1017 0, 917 0,
1018 0, 918 0,
1019 {}, 919 {},
@@ -1022,7 +922,6 @@ class DwarfOp {
1022 // 0x66 DW_OP_reg22 922 // 0x66 DW_OP_reg22
1023 "DW_OP_reg22", 923 "DW_OP_reg22",
1024 &DwarfOp::op_reg, 924 &DwarfOp::op_reg,
1025 DWARF_VERSION_2,
1026 0, 925 0,
1027 0, 926 0,
1028 {}, 927 {},
@@ -1031,7 +930,6 @@ class DwarfOp {
1031 // 0x67 DW_OP_reg23 930 // 0x67 DW_OP_reg23
1032 "DW_OP_reg23", 931 "DW_OP_reg23",
1033 &DwarfOp::op_reg, 932 &DwarfOp::op_reg,
1034 DWARF_VERSION_2,
1035 0, 933 0,
1036 0, 934 0,
1037 {}, 935 {},
@@ -1040,7 +938,6 @@ class DwarfOp {
1040 // 0x68 DW_OP_reg24 938 // 0x68 DW_OP_reg24
1041 "DW_OP_reg24", 939 "DW_OP_reg24",
1042 &DwarfOp::op_reg, 940 &DwarfOp::op_reg,
1043 DWARF_VERSION_2,
1044 0, 941 0,
1045 0, 942 0,
1046 {}, 943 {},
@@ -1049,7 +946,6 @@ class DwarfOp {
1049 // 0x69 DW_OP_reg25 946 // 0x69 DW_OP_reg25
1050 "DW_OP_reg25", 947 "DW_OP_reg25",
1051 &DwarfOp::op_reg, 948 &DwarfOp::op_reg,
1052 DWARF_VERSION_2,
1053 0, 949 0,
1054 0, 950 0,
1055 {}, 951 {},
@@ -1058,7 +954,6 @@ class DwarfOp {
1058 // 0x6a DW_OP_reg26 954 // 0x6a DW_OP_reg26
1059 "DW_OP_reg26", 955 "DW_OP_reg26",
1060 &DwarfOp::op_reg, 956 &DwarfOp::op_reg,
1061 DWARF_VERSION_2,
1062 0, 957 0,
1063 0, 958 0,
1064 {}, 959 {},
@@ -1067,7 +962,6 @@ class DwarfOp {
1067 // 0x6b DW_OP_reg27 962 // 0x6b DW_OP_reg27
1068 "DW_OP_reg27", 963 "DW_OP_reg27",
1069 &DwarfOp::op_reg, 964 &DwarfOp::op_reg,
1070 DWARF_VERSION_2,
1071 0, 965 0,
1072 0, 966 0,
1073 {}, 967 {},
@@ -1076,7 +970,6 @@ class DwarfOp {
1076 // 0x6c DW_OP_reg28 970 // 0x6c DW_OP_reg28
1077 "DW_OP_reg28", 971 "DW_OP_reg28",
1078 &DwarfOp::op_reg, 972 &DwarfOp::op_reg,
1079 DWARF_VERSION_2,
1080 0, 973 0,
1081 0, 974 0,
1082 {}, 975 {},
@@ -1085,7 +978,6 @@ class DwarfOp {
1085 // 0x6d DW_OP_reg29 978 // 0x6d DW_OP_reg29
1086 "DW_OP_reg29", 979 "DW_OP_reg29",
1087 &DwarfOp::op_reg, 980 &DwarfOp::op_reg,
1088 DWARF_VERSION_2,
1089 0, 981 0,
1090 0, 982 0,
1091 {}, 983 {},
@@ -1094,7 +986,6 @@ class DwarfOp {
1094 // 0x6e DW_OP_reg30 986 // 0x6e DW_OP_reg30
1095 "DW_OP_reg30", 987 "DW_OP_reg30",
1096 &DwarfOp::op_reg, 988 &DwarfOp::op_reg,
1097 DWARF_VERSION_2,
1098 0, 989 0,
1099 0, 990 0,
1100 {}, 991 {},
@@ -1103,7 +994,6 @@ class DwarfOp {
1103 // 0x6f DW_OP_reg31 994 // 0x6f DW_OP_reg31
1104 "DW_OP_reg31", 995 "DW_OP_reg31",
1105 &DwarfOp::op_reg, 996 &DwarfOp::op_reg,
1106 DWARF_VERSION_2,
1107 0, 997 0,
1108 0, 998 0,
1109 {}, 999 {},
@@ -1112,7 +1002,6 @@ class DwarfOp {
1112 // 0x70 DW_OP_breg0 1002 // 0x70 DW_OP_breg0
1113 "DW_OP_breg0", 1003 "DW_OP_breg0",
1114 &DwarfOp::op_breg, 1004 &DwarfOp::op_breg,
1115 DWARF_VERSION_2,
1116 0, 1005 0,
1117 1, 1006 1,
1118 {DW_EH_PE_sleb128}, 1007 {DW_EH_PE_sleb128},
@@ -1121,7 +1010,6 @@ class DwarfOp {
1121 // 0x71 DW_OP_breg1 1010 // 0x71 DW_OP_breg1
1122 "DW_OP_breg1", 1011 "DW_OP_breg1",
1123 &DwarfOp::op_breg, 1012 &DwarfOp::op_breg,
1124 DWARF_VERSION_2,
1125 0, 1013 0,
1126 1, 1014 1,
1127 {DW_EH_PE_sleb128}, 1015 {DW_EH_PE_sleb128},
@@ -1130,7 +1018,6 @@ class DwarfOp {
1130 // 0x72 DW_OP_breg2 1018 // 0x72 DW_OP_breg2
1131 "DW_OP_breg2", 1019 "DW_OP_breg2",
1132 &DwarfOp::op_breg, 1020 &DwarfOp::op_breg,
1133 DWARF_VERSION_2,
1134 0, 1021 0,
1135 1, 1022 1,
1136 {DW_EH_PE_sleb128}, 1023 {DW_EH_PE_sleb128},
@@ -1139,7 +1026,6 @@ class DwarfOp {
1139 // 0x73 DW_OP_breg3 1026 // 0x73 DW_OP_breg3
1140 "DW_OP_breg3", 1027 "DW_OP_breg3",
1141 &DwarfOp::op_breg, 1028 &DwarfOp::op_breg,
1142 DWARF_VERSION_2,
1143 0, 1029 0,
1144 1, 1030 1,
1145 {DW_EH_PE_sleb128}, 1031 {DW_EH_PE_sleb128},
@@ -1148,7 +1034,6 @@ class DwarfOp {
1148 // 0x74 DW_OP_breg4 1034 // 0x74 DW_OP_breg4
1149 "DW_OP_breg4", 1035 "DW_OP_breg4",
1150 &DwarfOp::op_breg, 1036 &DwarfOp::op_breg,
1151 DWARF_VERSION_2,
1152 0, 1037 0,
1153 1, 1038 1,
1154 {DW_EH_PE_sleb128}, 1039 {DW_EH_PE_sleb128},
@@ -1157,7 +1042,6 @@ class DwarfOp {
1157 // 0x75 DW_OP_breg5 1042 // 0x75 DW_OP_breg5
1158 "DW_OP_breg5", 1043 "DW_OP_breg5",
1159 &DwarfOp::op_breg, 1044 &DwarfOp::op_breg,
1160 DWARF_VERSION_2,
1161 0, 1045 0,
1162 1, 1046 1,
1163 {DW_EH_PE_sleb128}, 1047 {DW_EH_PE_sleb128},
@@ -1166,7 +1050,6 @@ class DwarfOp {
1166 // 0x76 DW_OP_breg6 1050 // 0x76 DW_OP_breg6
1167 "DW_OP_breg6", 1051 "DW_OP_breg6",
1168 &DwarfOp::op_breg, 1052 &DwarfOp::op_breg,
1169 DWARF_VERSION_2,
1170 0, 1053 0,
1171 1, 1054 1,
1172 {DW_EH_PE_sleb128}, 1055 {DW_EH_PE_sleb128},
@@ -1175,7 +1058,6 @@ class DwarfOp {
1175 // 0x77 DW_OP_breg7 1058 // 0x77 DW_OP_breg7
1176 "DW_OP_breg7", 1059 "DW_OP_breg7",
1177 &DwarfOp::op_breg, 1060 &DwarfOp::op_breg,
1178 DWARF_VERSION_2,
1179 0, 1061 0,
1180 1, 1062 1,
1181 {DW_EH_PE_sleb128}, 1063 {DW_EH_PE_sleb128},
@@ -1184,7 +1066,6 @@ class DwarfOp {
1184 // 0x78 DW_OP_breg8 1066 // 0x78 DW_OP_breg8
1185 "DW_OP_breg8", 1067 "DW_OP_breg8",
1186 &DwarfOp::op_breg, 1068 &DwarfOp::op_breg,
1187 DWARF_VERSION_2,
1188 0, 1069 0,
1189 1, 1070 1,
1190 {DW_EH_PE_sleb128}, 1071 {DW_EH_PE_sleb128},
@@ -1193,7 +1074,6 @@ class DwarfOp {
1193 // 0x79 DW_OP_breg9 1074 // 0x79 DW_OP_breg9
1194 "DW_OP_breg9", 1075 "DW_OP_breg9",
1195 &DwarfOp::op_breg, 1076 &DwarfOp::op_breg,
1196 DWARF_VERSION_2,
1197 0, 1077 0,
1198 1, 1078 1,
1199 {DW_EH_PE_sleb128}, 1079 {DW_EH_PE_sleb128},
@@ -1202,7 +1082,6 @@ class DwarfOp {
1202 // 0x7a DW_OP_breg10 1082 // 0x7a DW_OP_breg10
1203 "DW_OP_breg10", 1083 "DW_OP_breg10",
1204 &DwarfOp::op_breg, 1084 &DwarfOp::op_breg,
1205 DWARF_VERSION_2,
1206 0, 1085 0,
1207 1, 1086 1,
1208 {DW_EH_PE_sleb128}, 1087 {DW_EH_PE_sleb128},
@@ -1211,7 +1090,6 @@ class DwarfOp {
1211 // 0x7b DW_OP_breg11 1090 // 0x7b DW_OP_breg11
1212 "DW_OP_breg11", 1091 "DW_OP_breg11",
1213 &DwarfOp::op_breg, 1092 &DwarfOp::op_breg,
1214 DWARF_VERSION_2,
1215 0, 1093 0,
1216 1, 1094 1,
1217 {DW_EH_PE_sleb128}, 1095 {DW_EH_PE_sleb128},
@@ -1220,7 +1098,6 @@ class DwarfOp {
1220 // 0x7c DW_OP_breg12 1098 // 0x7c DW_OP_breg12
1221 "DW_OP_breg12", 1099 "DW_OP_breg12",
1222 &DwarfOp::op_breg, 1100 &DwarfOp::op_breg,
1223 DWARF_VERSION_2,
1224 0, 1101 0,
1225 1, 1102 1,
1226 {DW_EH_PE_sleb128}, 1103 {DW_EH_PE_sleb128},
@@ -1229,7 +1106,6 @@ class DwarfOp {
1229 // 0x7d DW_OP_breg13 1106 // 0x7d DW_OP_breg13
1230 "DW_OP_breg13", 1107 "DW_OP_breg13",
1231 &DwarfOp::op_breg, 1108 &DwarfOp::op_breg,
1232 DWARF_VERSION_2,
1233 0, 1109 0,
1234 1, 1110 1,
1235 {DW_EH_PE_sleb128}, 1111 {DW_EH_PE_sleb128},
@@ -1238,7 +1114,6 @@ class DwarfOp {
1238 // 0x7e DW_OP_breg14 1114 // 0x7e DW_OP_breg14
1239 "DW_OP_breg14", 1115 "DW_OP_breg14",
1240 &DwarfOp::op_breg, 1116 &DwarfOp::op_breg,
1241 DWARF_VERSION_2,
1242 0, 1117 0,
1243 1, 1118 1,
1244 {DW_EH_PE_sleb128}, 1119 {DW_EH_PE_sleb128},
@@ -1247,7 +1122,6 @@ class DwarfOp {
1247 // 0x7f DW_OP_breg15 1122 // 0x7f DW_OP_breg15
1248 "DW_OP_breg15", 1123 "DW_OP_breg15",
1249 &DwarfOp::op_breg, 1124 &DwarfOp::op_breg,
1250 DWARF_VERSION_2,
1251 0, 1125 0,
1252 1, 1126 1,
1253 {DW_EH_PE_sleb128}, 1127 {DW_EH_PE_sleb128},
@@ -1256,7 +1130,6 @@ class DwarfOp {
1256 // 0x80 DW_OP_breg16 1130 // 0x80 DW_OP_breg16
1257 "DW_OP_breg16", 1131 "DW_OP_breg16",
1258 &DwarfOp::op_breg, 1132 &DwarfOp::op_breg,
1259 DWARF_VERSION_2,
1260 0, 1133 0,
1261 1, 1134 1,
1262 {DW_EH_PE_sleb128}, 1135 {DW_EH_PE_sleb128},
@@ -1265,7 +1138,6 @@ class DwarfOp {
1265 // 0x81 DW_OP_breg17 1138 // 0x81 DW_OP_breg17
1266 "DW_OP_breg17", 1139 "DW_OP_breg17",
1267 &DwarfOp::op_breg, 1140 &DwarfOp::op_breg,
1268 DWARF_VERSION_2,
1269 0, 1141 0,
1270 1, 1142 1,
1271 {DW_EH_PE_sleb128}, 1143 {DW_EH_PE_sleb128},
@@ -1274,7 +1146,6 @@ class DwarfOp {
1274 // 0x82 DW_OP_breg18 1146 // 0x82 DW_OP_breg18
1275 "DW_OP_breg18", 1147 "DW_OP_breg18",
1276 &DwarfOp::op_breg, 1148 &DwarfOp::op_breg,
1277 DWARF_VERSION_2,
1278 0, 1149 0,
1279 1, 1150 1,
1280 {DW_EH_PE_sleb128}, 1151 {DW_EH_PE_sleb128},
@@ -1283,7 +1154,6 @@ class DwarfOp {
1283 // 0x83 DW_OP_breg19 1154 // 0x83 DW_OP_breg19
1284 "DW_OP_breg19", 1155 "DW_OP_breg19",
1285 &DwarfOp::op_breg, 1156 &DwarfOp::op_breg,
1286 DWARF_VERSION_2,
1287 0, 1157 0,
1288 1, 1158 1,
1289 {DW_EH_PE_sleb128}, 1159 {DW_EH_PE_sleb128},
@@ -1292,7 +1162,6 @@ class DwarfOp {
1292 // 0x84 DW_OP_breg20 1162 // 0x84 DW_OP_breg20
1293 "DW_OP_breg20", 1163 "DW_OP_breg20",
1294 &DwarfOp::op_breg, 1164 &DwarfOp::op_breg,
1295 DWARF_VERSION_2,
1296 0, 1165 0,
1297 1, 1166 1,
1298 {DW_EH_PE_sleb128}, 1167 {DW_EH_PE_sleb128},
@@ -1301,7 +1170,6 @@ class DwarfOp {
1301 // 0x85 DW_OP_breg21 1170 // 0x85 DW_OP_breg21
1302 "DW_OP_breg21", 1171 "DW_OP_breg21",
1303 &DwarfOp::op_breg, 1172 &DwarfOp::op_breg,
1304 DWARF_VERSION_2,
1305 0, 1173 0,
1306 1, 1174 1,
1307 {DW_EH_PE_sleb128}, 1175 {DW_EH_PE_sleb128},
@@ -1310,7 +1178,6 @@ class DwarfOp {
1310 // 0x86 DW_OP_breg22 1178 // 0x86 DW_OP_breg22
1311 "DW_OP_breg22", 1179 "DW_OP_breg22",
1312 &DwarfOp::op_breg, 1180 &DwarfOp::op_breg,
1313 DWARF_VERSION_2,
1314 0, 1181 0,
1315 1, 1182 1,
1316 {DW_EH_PE_sleb128}, 1183 {DW_EH_PE_sleb128},
@@ -1319,7 +1186,6 @@ class DwarfOp {
1319 // 0x87 DW_OP_breg23 1186 // 0x87 DW_OP_breg23
1320 "DW_OP_breg23", 1187 "DW_OP_breg23",
1321 &DwarfOp::op_breg, 1188 &DwarfOp::op_breg,
1322 DWARF_VERSION_2,
1323 0, 1189 0,
1324 1, 1190 1,
1325 {DW_EH_PE_sleb128}, 1191 {DW_EH_PE_sleb128},
@@ -1328,7 +1194,6 @@ class DwarfOp {
1328 // 0x88 DW_OP_breg24 1194 // 0x88 DW_OP_breg24
1329 "DW_OP_breg24", 1195 "DW_OP_breg24",
1330 &DwarfOp::op_breg, 1196 &DwarfOp::op_breg,
1331 DWARF_VERSION_2,
1332 0, 1197 0,
1333 1, 1198 1,
1334 {DW_EH_PE_sleb128}, 1199 {DW_EH_PE_sleb128},
@@ -1337,7 +1202,6 @@ class DwarfOp {
1337 // 0x89 DW_OP_breg25 1202 // 0x89 DW_OP_breg25
1338 "DW_OP_breg25", 1203 "DW_OP_breg25",
1339 &DwarfOp::op_breg, 1204 &DwarfOp::op_breg,
1340 DWARF_VERSION_2,
1341 0, 1205 0,
1342 1, 1206 1,
1343 {DW_EH_PE_sleb128}, 1207 {DW_EH_PE_sleb128},
@@ -1346,7 +1210,6 @@ class DwarfOp {
1346 // 0x8a DW_OP_breg26 1210 // 0x8a DW_OP_breg26
1347 "DW_OP_breg26", 1211 "DW_OP_breg26",
1348 &DwarfOp::op_breg, 1212 &DwarfOp::op_breg,
1349 DWARF_VERSION_2,
1350 0, 1213 0,
1351 1, 1214 1,
1352 {DW_EH_PE_sleb128}, 1215 {DW_EH_PE_sleb128},
@@ -1355,7 +1218,6 @@ class DwarfOp {
1355 // 0x8b DW_OP_breg27 1218 // 0x8b DW_OP_breg27
1356 "DW_OP_breg27", 1219 "DW_OP_breg27",
1357 &DwarfOp::op_breg, 1220 &DwarfOp::op_breg,
1358 DWARF_VERSION_2,
1359 0, 1221 0,
1360 1, 1222 1,
1361 {DW_EH_PE_sleb128}, 1223 {DW_EH_PE_sleb128},
@@ -1364,7 +1226,6 @@ class DwarfOp {
1364 // 0x8c DW_OP_breg28 1226 // 0x8c DW_OP_breg28
1365 "DW_OP_breg28", 1227 "DW_OP_breg28",
1366 &DwarfOp::op_breg, 1228 &DwarfOp::op_breg,
1367 DWARF_VERSION_2,
1368 0, 1229 0,
1369 1, 1230 1,
1370 {DW_EH_PE_sleb128}, 1231 {DW_EH_PE_sleb128},
@@ -1373,7 +1234,6 @@ class DwarfOp {
1373 // 0x8d DW_OP_breg29 1234 // 0x8d DW_OP_breg29
1374 "DW_OP_breg29", 1235 "DW_OP_breg29",
1375 &DwarfOp::op_breg, 1236 &DwarfOp::op_breg,
1376 DWARF_VERSION_2,
1377 0, 1237 0,
1378 1, 1238 1,
1379 {DW_EH_PE_sleb128}, 1239 {DW_EH_PE_sleb128},
@@ -1382,7 +1242,6 @@ class DwarfOp {
1382 // 0x8e DW_OP_breg30 1242 // 0x8e DW_OP_breg30
1383 "DW_OP_breg30", 1243 "DW_OP_breg30",
1384 &DwarfOp::op_breg, 1244 &DwarfOp::op_breg,
1385 DWARF_VERSION_2,
1386 0, 1245 0,
1387 1, 1246 1,
1388 {DW_EH_PE_sleb128}, 1247 {DW_EH_PE_sleb128},
@@ -1391,7 +1250,6 @@ class DwarfOp {
1391 // 0x8f DW_OP_breg31 1250 // 0x8f DW_OP_breg31
1392 "DW_OP_breg31", 1251 "DW_OP_breg31",
1393 &DwarfOp::op_breg, 1252 &DwarfOp::op_breg,
1394 DWARF_VERSION_2,
1395 0, 1253 0,
1396 1, 1254 1,
1397 {DW_EH_PE_sleb128}, 1255 {DW_EH_PE_sleb128},
@@ -1400,7 +1258,6 @@ class DwarfOp {
1400 // 0x90 DW_OP_regx 1258 // 0x90 DW_OP_regx
1401 "DW_OP_regx", 1259 "DW_OP_regx",
1402 &DwarfOp::op_regx, 1260 &DwarfOp::op_regx,
1403 DWARF_VERSION_2,
1404 0, 1261 0,
1405 1, 1262 1,
1406 {DW_EH_PE_uleb128}, 1263 {DW_EH_PE_uleb128},
@@ -1409,7 +1266,6 @@ class DwarfOp {
1409 // 0x91 DW_OP_fbreg 1266 // 0x91 DW_OP_fbreg
1410 "DW_OP_fbreg", 1267 "DW_OP_fbreg",
1411 &DwarfOp::op_not_implemented, 1268 &DwarfOp::op_not_implemented,
1412 DWARF_VERSION_2,
1413 0, 1269 0,
1414 1, 1270 1,
1415 {DW_EH_PE_sleb128}, 1271 {DW_EH_PE_sleb128},
@@ -1418,7 +1274,6 @@ class DwarfOp {
1418 // 0x92 DW_OP_bregx 1274 // 0x92 DW_OP_bregx
1419 "DW_OP_bregx", 1275 "DW_OP_bregx",
1420 &DwarfOp::op_bregx, 1276 &DwarfOp::op_bregx,
1421 DWARF_VERSION_2,
1422 0, 1277 0,
1423 2, 1278 2,
1424 {DW_EH_PE_uleb128, DW_EH_PE_sleb128}, 1279 {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
@@ -1427,7 +1282,6 @@ class DwarfOp {
1427 // 0x93 DW_OP_piece 1282 // 0x93 DW_OP_piece
1428 "DW_OP_piece", 1283 "DW_OP_piece",
1429 &DwarfOp::op_not_implemented, 1284 &DwarfOp::op_not_implemented,
1430 DWARF_VERSION_2,
1431 0, 1285 0,
1432 1, 1286 1,
1433 {DW_EH_PE_uleb128}, 1287 {DW_EH_PE_uleb128},
@@ -1436,7 +1290,6 @@ class DwarfOp {
1436 // 0x94 DW_OP_deref_size 1290 // 0x94 DW_OP_deref_size
1437 "DW_OP_deref_size", 1291 "DW_OP_deref_size",
1438 &DwarfOp::op_deref_size, 1292 &DwarfOp::op_deref_size,
1439 DWARF_VERSION_2,
1440 1, 1293 1,
1441 1, 1294 1,
1442 {DW_EH_PE_udata1}, 1295 {DW_EH_PE_udata1},
@@ -1445,7 +1298,6 @@ class DwarfOp {
1445 // 0x95 DW_OP_xderef_size 1298 // 0x95 DW_OP_xderef_size
1446 "DW_OP_xderef_size", 1299 "DW_OP_xderef_size",
1447 &DwarfOp::op_not_implemented, 1300 &DwarfOp::op_not_implemented,
1448 DWARF_VERSION_2,
1449 0, 1301 0,
1450 1, 1302 1,
1451 {DW_EH_PE_udata1}, 1303 {DW_EH_PE_udata1},
@@ -1454,7 +1306,6 @@ class DwarfOp {
1454 // 0x96 DW_OP_nop 1306 // 0x96 DW_OP_nop
1455 "DW_OP_nop", 1307 "DW_OP_nop",
1456 &DwarfOp::op_nop, 1308 &DwarfOp::op_nop,
1457 DWARF_VERSION_2,
1458 0, 1309 0,
1459 0, 1310 0,
1460 {}, 1311 {},
@@ -1463,7 +1314,6 @@ class DwarfOp {
1463 // 0x97 DW_OP_push_object_address 1314 // 0x97 DW_OP_push_object_address
1464 "DW_OP_push_object_address", 1315 "DW_OP_push_object_address",
1465 &DwarfOp::op_not_implemented, 1316 &DwarfOp::op_not_implemented,
1466 DWARF_VERSION_3,
1467 0, 1317 0,
1468 0, 1318 0,
1469 {}, 1319 {},
@@ -1472,7 +1322,6 @@ class DwarfOp {
1472 // 0x98 DW_OP_call2 1322 // 0x98 DW_OP_call2
1473 "DW_OP_call2", 1323 "DW_OP_call2",
1474 &DwarfOp::op_not_implemented, 1324 &DwarfOp::op_not_implemented,
1475 DWARF_VERSION_3,
1476 0, 1325 0,
1477 1, 1326 1,
1478 {DW_EH_PE_udata2}, 1327 {DW_EH_PE_udata2},
@@ -1481,7 +1330,6 @@ class DwarfOp {
1481 // 0x99 DW_OP_call4 1330 // 0x99 DW_OP_call4
1482 "DW_OP_call4", 1331 "DW_OP_call4",
1483 &DwarfOp::op_not_implemented, 1332 &DwarfOp::op_not_implemented,
1484 DWARF_VERSION_3,
1485 0, 1333 0,
1486 1, 1334 1,
1487 {DW_EH_PE_udata4}, 1335 {DW_EH_PE_udata4},
@@ -1490,7 +1338,6 @@ class DwarfOp {
1490 // 0x9a DW_OP_call_ref 1338 // 0x9a DW_OP_call_ref
1491 "DW_OP_call_ref", 1339 "DW_OP_call_ref",
1492 &DwarfOp::op_not_implemented, 1340 &DwarfOp::op_not_implemented,
1493 DWARF_VERSION_3,
1494 0, 1341 0,
1495 0, // Has a different sized operand (4 bytes or 8 bytes). 1342 0, // Has a different sized operand (4 bytes or 8 bytes).
1496 {}, 1343 {},
@@ -1499,7 +1346,6 @@ class DwarfOp {
1499 // 0x9b DW_OP_form_tls_address 1346 // 0x9b DW_OP_form_tls_address
1500 "DW_OP_form_tls_address", 1347 "DW_OP_form_tls_address",
1501 &DwarfOp::op_not_implemented, 1348 &DwarfOp::op_not_implemented,
1502 DWARF_VERSION_3,
1503 0, 1349 0,
1504 0, 1350 0,
1505 {}, 1351 {},
@@ -1508,7 +1354,6 @@ class DwarfOp {
1508 // 0x9c DW_OP_call_frame_cfa 1354 // 0x9c DW_OP_call_frame_cfa
1509 "DW_OP_call_frame_cfa", 1355 "DW_OP_call_frame_cfa",
1510 &DwarfOp::op_not_implemented, 1356 &DwarfOp::op_not_implemented,
1511 DWARF_VERSION_3,
1512 0, 1357 0,
1513 0, 1358 0,
1514 {}, 1359 {},
@@ -1517,7 +1362,6 @@ class DwarfOp {
1517 // 0x9d DW_OP_bit_piece 1362 // 0x9d DW_OP_bit_piece
1518 "DW_OP_bit_piece", 1363 "DW_OP_bit_piece",
1519 &DwarfOp::op_not_implemented, 1364 &DwarfOp::op_not_implemented,
1520 DWARF_VERSION_3,
1521 0, 1365 0,
1522 2, 1366 2,
1523 {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, 1367 {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
@@ -1526,7 +1370,6 @@ class DwarfOp {
1526 // 0x9e DW_OP_implicit_value 1370 // 0x9e DW_OP_implicit_value
1527 "DW_OP_implicit_value", 1371 "DW_OP_implicit_value",
1528 &DwarfOp::op_not_implemented, 1372 &DwarfOp::op_not_implemented,
1529 DWARF_VERSION_4,
1530 0, 1373 0,
1531 1, 1374 1,
1532 {DW_EH_PE_uleb128}, 1375 {DW_EH_PE_uleb128},
@@ -1535,107 +1378,106 @@ class DwarfOp {
1535 // 0x9f DW_OP_stack_value 1378 // 0x9f DW_OP_stack_value
1536 "DW_OP_stack_value", 1379 "DW_OP_stack_value",
1537 &DwarfOp::op_not_implemented, 1380 &DwarfOp::op_not_implemented,
1538 DWARF_VERSION_4, 1381 1,
1539 1, 1382 0,
1540 0, 1383 {},
1541 {}, 1384 },
1542 }, 1385 {nullptr, nullptr, 0, 0, {}}, // 0xa0 illegal op
1543 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa0 illegal op 1386 {nullptr, nullptr, 0, 0, {}}, // 0xa1 illegal op
1544 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa1 illegal op 1387 {nullptr, nullptr, 0, 0, {}}, // 0xa2 illegal op
1545 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa2 illegal op 1388 {nullptr, nullptr, 0, 0, {}}, // 0xa3 illegal op
1546 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa3 illegal op 1389 {nullptr, nullptr, 0, 0, {}}, // 0xa4 illegal op
1547 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa4 illegal op 1390 {nullptr, nullptr, 0, 0, {}}, // 0xa5 illegal op
1548 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa5 illegal op 1391 {nullptr, nullptr, 0, 0, {}}, // 0xa6 illegal op
1549 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa6 illegal op 1392 {nullptr, nullptr, 0, 0, {}}, // 0xa7 illegal op
1550 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa7 illegal op 1393 {nullptr, nullptr, 0, 0, {}}, // 0xa8 illegal op
1551 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa8 illegal op 1394 {nullptr, nullptr, 0, 0, {}}, // 0xa9 illegal op
1552 {nullptr, nullptr, 0, 0, 0, {}}, // 0xa9 illegal op 1395 {nullptr, nullptr, 0, 0, {}}, // 0xaa illegal op
1553 {nullptr, nullptr, 0, 0, 0, {}}, // 0xaa illegal op 1396 {nullptr, nullptr, 0, 0, {}}, // 0xab illegal op
1554 {nullptr, nullptr, 0, 0, 0, {}}, // 0xab illegal op 1397 {nullptr, nullptr, 0, 0, {}}, // 0xac illegal op
1555 {nullptr, nullptr, 0, 0, 0, {}}, // 0xac illegal op 1398 {nullptr, nullptr, 0, 0, {}}, // 0xad illegal op
1556 {nullptr, nullptr, 0, 0, 0, {}}, // 0xad illegal op 1399 {nullptr, nullptr, 0, 0, {}}, // 0xae illegal op
1557 {nullptr, nullptr, 0, 0, 0, {}}, // 0xae illegal op 1400 {nullptr, nullptr, 0, 0, {}}, // 0xaf illegal op
1558 {nullptr, nullptr, 0, 0, 0, {}}, // 0xaf illegal op 1401 {nullptr, nullptr, 0, 0, {}}, // 0xb0 illegal op
1559 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb0 illegal op 1402 {nullptr, nullptr, 0, 0, {}}, // 0xb1 illegal op
1560 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb1 illegal op 1403 {nullptr, nullptr, 0, 0, {}}, // 0xb2 illegal op
1561 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb2 illegal op 1404 {nullptr, nullptr, 0, 0, {}}, // 0xb3 illegal op
1562 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb3 illegal op 1405 {nullptr, nullptr, 0, 0, {}}, // 0xb4 illegal op
1563 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb4 illegal op 1406 {nullptr, nullptr, 0, 0, {}}, // 0xb5 illegal op
1564 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb5 illegal op 1407 {nullptr, nullptr, 0, 0, {}}, // 0xb6 illegal op
1565 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb6 illegal op 1408 {nullptr, nullptr, 0, 0, {}}, // 0xb7 illegal op
1566 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb7 illegal op 1409 {nullptr, nullptr, 0, 0, {}}, // 0xb8 illegal op
1567 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb8 illegal op 1410 {nullptr, nullptr, 0, 0, {}}, // 0xb9 illegal op
1568 {nullptr, nullptr, 0, 0, 0, {}}, // 0xb9 illegal op 1411 {nullptr, nullptr, 0, 0, {}}, // 0xba illegal op
1569 {nullptr, nullptr, 0, 0, 0, {}}, // 0xba illegal op 1412 {nullptr, nullptr, 0, 0, {}}, // 0xbb illegal op
1570 {nullptr, nullptr, 0, 0, 0, {}}, // 0xbb illegal op 1413 {nullptr, nullptr, 0, 0, {}}, // 0xbc illegal op
1571 {nullptr, nullptr, 0, 0, 0, {}}, // 0xbc illegal op 1414 {nullptr, nullptr, 0, 0, {}}, // 0xbd illegal op
1572 {nullptr, nullptr, 0, 0, 0, {}}, // 0xbd illegal op 1415 {nullptr, nullptr, 0, 0, {}}, // 0xbe illegal op
1573 {nullptr, nullptr, 0, 0, 0, {}}, // 0xbe illegal op 1416 {nullptr, nullptr, 0, 0, {}}, // 0xbf illegal op
1574 {nullptr, nullptr, 0, 0, 0, {}}, // 0xbf illegal op 1417 {nullptr, nullptr, 0, 0, {}}, // 0xc0 illegal op
1575 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc0 illegal op 1418 {nullptr, nullptr, 0, 0, {}}, // 0xc1 illegal op
1576 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc1 illegal op 1419 {nullptr, nullptr, 0, 0, {}}, // 0xc2 illegal op
1577 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc2 illegal op 1420 {nullptr, nullptr, 0, 0, {}}, // 0xc3 illegal op
1578 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc3 illegal op 1421 {nullptr, nullptr, 0, 0, {}}, // 0xc4 illegal op
1579 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc4 illegal op 1422 {nullptr, nullptr, 0, 0, {}}, // 0xc5 illegal op
1580 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc5 illegal op 1423 {nullptr, nullptr, 0, 0, {}}, // 0xc6 illegal op
1581 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc6 illegal op 1424 {nullptr, nullptr, 0, 0, {}}, // 0xc7 illegal op
1582 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc7 illegal op 1425 {nullptr, nullptr, 0, 0, {}}, // 0xc8 illegal op
1583 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc8 illegal op 1426 {nullptr, nullptr, 0, 0, {}}, // 0xc9 illegal op
1584 {nullptr, nullptr, 0, 0, 0, {}}, // 0xc9 illegal op 1427 {nullptr, nullptr, 0, 0, {}}, // 0xca illegal op
1585 {nullptr, nullptr, 0, 0, 0, {}}, // 0xca illegal op 1428 {nullptr, nullptr, 0, 0, {}}, // 0xcb illegal op
1586 {nullptr, nullptr, 0, 0, 0, {}}, // 0xcb illegal op 1429 {nullptr, nullptr, 0, 0, {}}, // 0xcc illegal op
1587 {nullptr, nullptr, 0, 0, 0, {}}, // 0xcc illegal op 1430 {nullptr, nullptr, 0, 0, {}}, // 0xcd illegal op
1588 {nullptr, nullptr, 0, 0, 0, {}}, // 0xcd illegal op 1431 {nullptr, nullptr, 0, 0, {}}, // 0xce illegal op
1589 {nullptr, nullptr, 0, 0, 0, {}}, // 0xce illegal op 1432 {nullptr, nullptr, 0, 0, {}}, // 0xcf illegal op
1590 {nullptr, nullptr, 0, 0, 0, {}}, // 0xcf illegal op 1433 {nullptr, nullptr, 0, 0, {}}, // 0xd0 illegal op
1591 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd0 illegal op 1434 {nullptr, nullptr, 0, 0, {}}, // 0xd1 illegal op
1592 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd1 illegal op 1435 {nullptr, nullptr, 0, 0, {}}, // 0xd2 illegal op
1593 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd2 illegal op 1436 {nullptr, nullptr, 0, 0, {}}, // 0xd3 illegal op
1594 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd3 illegal op 1437 {nullptr, nullptr, 0, 0, {}}, // 0xd4 illegal op
1595 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd4 illegal op 1438 {nullptr, nullptr, 0, 0, {}}, // 0xd5 illegal op
1596 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd5 illegal op 1439 {nullptr, nullptr, 0, 0, {}}, // 0xd6 illegal op
1597 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd6 illegal op 1440 {nullptr, nullptr, 0, 0, {}}, // 0xd7 illegal op
1598 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd7 illegal op 1441 {nullptr, nullptr, 0, 0, {}}, // 0xd8 illegal op
1599 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd8 illegal op 1442 {nullptr, nullptr, 0, 0, {}}, // 0xd9 illegal op
1600 {nullptr, nullptr, 0, 0, 0, {}}, // 0xd9 illegal op 1443 {nullptr, nullptr, 0, 0, {}}, // 0xda illegal op
1601 {nullptr, nullptr, 0, 0, 0, {}}, // 0xda illegal op 1444 {nullptr, nullptr, 0, 0, {}}, // 0xdb illegal op
1602 {nullptr, nullptr, 0, 0, 0, {}}, // 0xdb illegal op 1445 {nullptr, nullptr, 0, 0, {}}, // 0xdc illegal op
1603 {nullptr, nullptr, 0, 0, 0, {}}, // 0xdc illegal op 1446 {nullptr, nullptr, 0, 0, {}}, // 0xdd illegal op
1604 {nullptr, nullptr, 0, 0, 0, {}}, // 0xdd illegal op 1447 {nullptr, nullptr, 0, 0, {}}, // 0xde illegal op
1605 {nullptr, nullptr, 0, 0, 0, {}}, // 0xde illegal op 1448 {nullptr, nullptr, 0, 0, {}}, // 0xdf illegal op
1606 {nullptr, nullptr, 0, 0, 0, {}}, // 0xdf illegal op 1449 {nullptr, nullptr, 0, 0, {}}, // 0xe0 DW_OP_lo_user
1607 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe0 DW_OP_lo_user 1450 {nullptr, nullptr, 0, 0, {}}, // 0xe1 illegal op
1608 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe1 illegal op 1451 {nullptr, nullptr, 0, 0, {}}, // 0xe2 illegal op
1609 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe2 illegal op 1452 {nullptr, nullptr, 0, 0, {}}, // 0xe3 illegal op
1610 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe3 illegal op 1453 {nullptr, nullptr, 0, 0, {}}, // 0xe4 illegal op
1611 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe4 illegal op 1454 {nullptr, nullptr, 0, 0, {}}, // 0xe5 illegal op
1612 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe5 illegal op 1455 {nullptr, nullptr, 0, 0, {}}, // 0xe6 illegal op
1613 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe6 illegal op 1456 {nullptr, nullptr, 0, 0, {}}, // 0xe7 illegal op
1614 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe7 illegal op 1457 {nullptr, nullptr, 0, 0, {}}, // 0xe8 illegal op
1615 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe8 illegal op 1458 {nullptr, nullptr, 0, 0, {}}, // 0xe9 illegal op
1616 {nullptr, nullptr, 0, 0, 0, {}}, // 0xe9 illegal op 1459 {nullptr, nullptr, 0, 0, {}}, // 0xea illegal op
1617 {nullptr, nullptr, 0, 0, 0, {}}, // 0xea illegal op 1460 {nullptr, nullptr, 0, 0, {}}, // 0xeb illegal op
1618 {nullptr, nullptr, 0, 0, 0, {}}, // 0xeb illegal op 1461 {nullptr, nullptr, 0, 0, {}}, // 0xec illegal op
1619 {nullptr, nullptr, 0, 0, 0, {}}, // 0xec illegal op 1462 {nullptr, nullptr, 0, 0, {}}, // 0xed illegal op
1620 {nullptr, nullptr, 0, 0, 0, {}}, // 0xed illegal op 1463 {nullptr, nullptr, 0, 0, {}}, // 0xee illegal op
1621 {nullptr, nullptr, 0, 0, 0, {}}, // 0xee illegal op 1464 {nullptr, nullptr, 0, 0, {}}, // 0xef illegal op
1622 {nullptr, nullptr, 0, 0, 0, {}}, // 0xef illegal op 1465 {nullptr, nullptr, 0, 0, {}}, // 0xf0 illegal op
1623 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf0 illegal op 1466 {nullptr, nullptr, 0, 0, {}}, // 0xf1 illegal op
1624 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf1 illegal op 1467 {nullptr, nullptr, 0, 0, {}}, // 0xf2 illegal op
1625 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf2 illegal op 1468 {nullptr, nullptr, 0, 0, {}}, // 0xf3 illegal op
1626 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf3 illegal op 1469 {nullptr, nullptr, 0, 0, {}}, // 0xf4 illegal op
1627 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf4 illegal op 1470 {nullptr, nullptr, 0, 0, {}}, // 0xf5 illegal op
1628 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf5 illegal op 1471 {nullptr, nullptr, 0, 0, {}}, // 0xf6 illegal op
1629 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf6 illegal op 1472 {nullptr, nullptr, 0, 0, {}}, // 0xf7 illegal op
1630 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf7 illegal op 1473 {nullptr, nullptr, 0, 0, {}}, // 0xf8 illegal op
1631 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf8 illegal op 1474 {nullptr, nullptr, 0, 0, {}}, // 0xf9 illegal op
1632 {nullptr, nullptr, 0, 0, 0, {}}, // 0xf9 illegal op 1475 {nullptr, nullptr, 0, 0, {}}, // 0xfa illegal op
1633 {nullptr, nullptr, 0, 0, 0, {}}, // 0xfa illegal op 1476 {nullptr, nullptr, 0, 0, {}}, // 0xfb illegal op
1634 {nullptr, nullptr, 0, 0, 0, {}}, // 0xfb illegal op 1477 {nullptr, nullptr, 0, 0, {}}, // 0xfc illegal op
1635 {nullptr, nullptr, 0, 0, 0, {}}, // 0xfc illegal op 1478 {nullptr, nullptr, 0, 0, {}}, // 0xfd illegal op
1636 {nullptr, nullptr, 0, 0, 0, {}}, // 0xfd illegal op 1479 {nullptr, nullptr, 0, 0, {}}, // 0xfe illegal op
1637 {nullptr, nullptr, 0, 0, 0, {}}, // 0xfe illegal op 1480 {nullptr, nullptr, 0, 0, {}}, // 0xff DW_OP_hi_user
1638 {nullptr, nullptr, 0, 0, 0, {}}, // 0xff DW_OP_hi_user
1639 }; 1481 };
1640}; 1482};
1641 1483
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 4e94f887d..764979863 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -26,16 +26,14 @@
26#include <unwindstack/Regs.h> 26#include <unwindstack/Regs.h>
27 27
28#include "DwarfCfa.h" 28#include "DwarfCfa.h"
29#include "DwarfEncoding.h"
30#include "DwarfOp.h"
31
32#include "DwarfDebugFrame.h" 29#include "DwarfDebugFrame.h"
33#include "DwarfEhFrame.h" 30#include "DwarfEhFrame.h"
31#include "DwarfEncoding.h"
32#include "DwarfOp.h"
33#include "RegsInfo.h"
34 34
35namespace unwindstack { 35namespace unwindstack {
36 36
37constexpr uint64_t DEX_PC_REG = 0x20444558;
38
39DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {} 37DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
40 38
41const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) { 39const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
@@ -75,14 +73,17 @@ bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* f
75} 73}
76 74
77template <typename AddressType> 75template <typename AddressType>
78bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uint8_t version, 76bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory,
79 Memory* regular_memory, AddressType* value) { 77 AddressType* value,
78 RegsInfo<AddressType>* regs_info,
79 bool* is_dex_pc) {
80 DwarfOp<AddressType> op(&memory_, regular_memory); 80 DwarfOp<AddressType> op(&memory_, regular_memory);
81 op.set_regs_info(regs_info);
81 82
82 // Need to evaluate the op data. 83 // Need to evaluate the op data.
83 uint64_t start = loc.values[1]; 84 uint64_t end = loc.values[1];
84 uint64_t end = start + loc.values[0]; 85 uint64_t start = end - loc.values[0];
85 if (!op.Eval(start, end, version)) { 86 if (!op.Eval(start, end)) {
86 last_error_ = op.last_error(); 87 last_error_ = op.last_error();
87 return false; 88 return false;
88 } 89 }
@@ -96,6 +97,9 @@ bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uin
96 return false; 97 return false;
97 } 98 }
98 *value = op.StackAt(0); 99 *value = op.StackAt(0);
100 if (is_dex_pc != nullptr && op.dex_pc_set()) {
101 *is_dex_pc = true;
102 }
99 return true; 103 return true;
100} 104}
101 105
@@ -103,12 +107,10 @@ template <typename AddressType>
103struct EvalInfo { 107struct EvalInfo {
104 const dwarf_loc_regs_t* loc_regs; 108 const dwarf_loc_regs_t* loc_regs;
105 const DwarfCie* cie; 109 const DwarfCie* cie;
106 RegsImpl<AddressType>* cur_regs;
107 Memory* regular_memory; 110 Memory* regular_memory;
108 AddressType cfa; 111 AddressType cfa;
109 bool return_address_undefined = false; 112 bool return_address_undefined = false;
110 uint64_t reg_map = 0; 113 RegsInfo<AddressType> regs_info;
111 AddressType reg_values[64];
112}; 114};
113 115
114template <typename AddressType> 116template <typename AddressType>
@@ -129,32 +131,18 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3
129 break; 131 break;
130 case DWARF_LOCATION_REGISTER: { 132 case DWARF_LOCATION_REGISTER: {
131 uint32_t cur_reg = loc->values[0]; 133 uint32_t cur_reg = loc->values[0];
132 if (cur_reg >= eval_info->cur_regs->total_regs()) { 134 if (cur_reg >= eval_info->regs_info.Total()) {
133 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 135 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
134 return false; 136 return false;
135 } 137 }
136 AddressType* cur_reg_ptr = &(*eval_info->cur_regs)[cur_reg]; 138 *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1];
137 const auto& entry = eval_info->loc_regs->find(cur_reg);
138 if (entry != eval_info->loc_regs->end()) {
139 if (!(eval_info->reg_map & (1 << cur_reg))) {
140 eval_info->reg_map |= 1 << cur_reg;
141 eval_info->reg_values[cur_reg] = *cur_reg_ptr;
142 if (!EvalRegister(&entry->second, cur_reg, cur_reg_ptr, eval_info)) {
143 return false;
144 }
145 }
146
147 // Use the register value from before any evaluations.
148 *reg_ptr = eval_info->reg_values[cur_reg] + loc->values[1];
149 } else {
150 *reg_ptr = *cur_reg_ptr + loc->values[1];
151 }
152 break; 139 break;
153 } 140 }
154 case DWARF_LOCATION_EXPRESSION: 141 case DWARF_LOCATION_EXPRESSION:
155 case DWARF_LOCATION_VAL_EXPRESSION: { 142 case DWARF_LOCATION_VAL_EXPRESSION: {
156 AddressType value; 143 AddressType value;
157 if (!EvalExpression(*loc, eval_info->cie->version, regular_memory, &value)) { 144 bool is_dex_pc = false;
145 if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) {
158 return false; 146 return false;
159 } 147 }
160 if (loc->type == DWARF_LOCATION_EXPRESSION) { 148 if (loc->type == DWARF_LOCATION_EXPRESSION) {
@@ -165,6 +153,9 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3
165 } 153 }
166 } else { 154 } else {
167 *reg_ptr = value; 155 *reg_ptr = value;
156 if (is_dex_pc) {
157 eval_info->regs_info.regs->set_dex_pc(value);
158 }
168 } 159 }
169 break; 160 break;
170 } 161 }
@@ -201,8 +192,10 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
201 192
202 AddressType prev_cfa = regs->sp(); 193 AddressType prev_cfa = regs->sp();
203 194
204 EvalInfo<AddressType> eval_info{ 195 EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
205 .loc_regs = &loc_regs, .cie = cie, .regular_memory = regular_memory, .cur_regs = cur_regs}; 196 .cie = cie,
197 .regular_memory = regular_memory,
198 .regs_info = RegsInfo<AddressType>(cur_regs)};
206 const DwarfLocation* loc = &cfa_entry->second; 199 const DwarfLocation* loc = &cfa_entry->second;
207 // Only a few location types are valid for the cfa. 200 // Only a few location types are valid for the cfa.
208 switch (loc->type) { 201 switch (loc->type) {
@@ -224,7 +217,7 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
224 case DWARF_LOCATION_EXPRESSION: 217 case DWARF_LOCATION_EXPRESSION:
225 case DWARF_LOCATION_VAL_EXPRESSION: { 218 case DWARF_LOCATION_VAL_EXPRESSION: {
226 AddressType value; 219 AddressType value;
227 if (!EvalExpression(*loc, cie->version, regular_memory, &value)) { 220 if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) {
228 return false; 221 return false;
229 } 222 }
230 if (loc->type == DWARF_LOCATION_EXPRESSION) { 223 if (loc->type == DWARF_LOCATION_EXPRESSION) {
@@ -249,28 +242,15 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
249 if (reg == CFA_REG) continue; 242 if (reg == CFA_REG) continue;
250 243
251 AddressType* reg_ptr; 244 AddressType* reg_ptr;
252 AddressType dex_pc = 0; 245 if (reg >= cur_regs->total_regs()) {
253 if (reg == DEX_PC_REG) { 246 // Skip this unknown register.
254 // Special register that indicates this is a dex pc.
255 dex_pc = 0;
256 reg_ptr = &dex_pc;
257 } else if (reg >= cur_regs->total_regs() || eval_info.reg_map & (1 << reg)) {
258 // Skip this unknown register, or a register that has already been
259 // processed.
260 continue; 247 continue;
261 } else {
262 reg_ptr = &(*cur_regs)[reg];
263 eval_info.reg_map |= 1 << reg;
264 eval_info.reg_values[reg] = *reg_ptr;
265 } 248 }
266 249
250 reg_ptr = eval_info.regs_info.Save(reg);
267 if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { 251 if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
268 return false; 252 return false;
269 } 253 }
270
271 if (reg == DEX_PC_REG) {
272 cur_regs->set_dex_pc(dex_pc);
273 }
274 } 254 }
275 255
276 // Find the return address location. 256 // Find the return address location.
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index dbf772e5d..02f8a9ae0 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -20,6 +20,7 @@
20#include <memory> 20#include <memory>
21#include <mutex> 21#include <mutex>
22#include <string> 22#include <string>
23#include <utility>
23 24
24#define LOG_TAG "unwind" 25#define LOG_TAG "unwind"
25#include <log/log.h> 26#include <log/log.h>
@@ -36,7 +37,7 @@
36namespace unwindstack { 37namespace unwindstack {
37 38
38bool Elf::cache_enabled_; 39bool Elf::cache_enabled_;
39std::unordered_map<std::string, std::shared_ptr<Elf>>* Elf::cache_; 40std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* Elf::cache_;
40std::mutex* Elf::cache_lock_; 41std::mutex* Elf::cache_lock_;
41 42
42bool Elf::Init(bool init_gnu_debugdata) { 43bool Elf::Init(bool init_gnu_debugdata) {
@@ -308,7 +309,7 @@ uint64_t Elf::GetLoadBias(Memory* memory) {
308void Elf::SetCachingEnabled(bool enable) { 309void Elf::SetCachingEnabled(bool enable) {
309 if (!cache_enabled_ && enable) { 310 if (!cache_enabled_ && enable) {
310 cache_enabled_ = true; 311 cache_enabled_ = true;
311 cache_ = new std::unordered_map<std::string, std::shared_ptr<Elf>>; 312 cache_ = new std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>;
312 cache_lock_ = new std::mutex; 313 cache_lock_ = new std::mutex;
313 } else if (cache_enabled_ && !enable) { 314 } else if (cache_enabled_ && !enable) {
314 cache_enabled_ = false; 315 cache_enabled_ = false;
@@ -326,18 +327,54 @@ void Elf::CacheUnlock() {
326} 327}
327 328
328void Elf::CacheAdd(MapInfo* info) { 329void Elf::CacheAdd(MapInfo* info) {
329 if (info->offset == 0) { 330 // If elf_offset != 0, then cache both name:offset and name.
330 (*cache_)[info->name] = info->elf; 331 // The cached name is used to do lookups if multiple maps for the same
331 } else { 332 // named elf file exist.
332 std::string name(info->name + ':' + std::to_string(info->offset)); 333 // For example, if there are two maps boot.odex:1000 and boot.odex:2000
333 (*cache_)[name] = info->elf; 334 // where each reference the entire boot.odex, the cache will properly
335 // use the same cached elf object.
336
337 if (info->offset == 0 || info->elf_offset != 0) {
338 (*cache_)[info->name] = std::make_pair(info->elf, true);
339 }
340
341 if (info->offset != 0) {
342 // The second element in the pair indicates whether elf_offset should
343 // be set to offset when getting out of the cache.
344 (*cache_)[info->name + ':' + std::to_string(info->offset)] =
345 std::make_pair(info->elf, info->elf_offset != 0);
334 } 346 }
335} 347}
336 348
337bool Elf::CacheGet(const std::string& name, std::shared_ptr<Elf>* elf) { 349bool Elf::CacheAfterCreateMemory(MapInfo* info) {
350 if (info->name.empty() || info->offset == 0 || info->elf_offset == 0) {
351 return false;
352 }
353
354 auto entry = cache_->find(info->name);
355 if (entry == cache_->end()) {
356 return false;
357 }
358
359 // In this case, the whole file is the elf, and the name has already
360 // been cached. Add an entry at name:offset to get this directly out
361 // of the cache next time.
362 info->elf = entry->second.first;
363 (*cache_)[info->name + ':' + std::to_string(info->offset)] = std::make_pair(info->elf, true);
364 return true;
365}
366
367bool Elf::CacheGet(MapInfo* info) {
368 std::string name(info->name);
369 if (info->offset != 0) {
370 name += ':' + std::to_string(info->offset);
371 }
338 auto entry = cache_->find(name); 372 auto entry = cache_->find(name);
339 if (entry != cache_->end()) { 373 if (entry != cache_->end()) {
340 *elf = entry->second; 374 info->elf = entry->second.first;
375 if (entry->second.second) {
376 info->elf_offset = info->offset;
377 }
341 return true; 378 return true;
342 } 379 }
343 return false; 380 return false;
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index e41308171..10afe33be 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -19,6 +19,7 @@
19 19
20#include <memory> 20#include <memory>
21#include <string> 21#include <string>
22#include <utility>
22 23
23#include <7zCrc.h> 24#include <7zCrc.h>
24#include <Xz.h> 25#include <Xz.h>
@@ -322,19 +323,13 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
322 // Skip the first header, it's always going to be NULL. 323 // Skip the first header, it's always going to be NULL.
323 offset += ehdr.e_shentsize; 324 offset += ehdr.e_shentsize;
324 for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) { 325 for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
325 if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) { 326 if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
326 last_error_.code = ERROR_MEMORY_INVALID; 327 last_error_.code = ERROR_MEMORY_INVALID;
327 last_error_.address = 328 last_error_.address = offset;
328 offset + reinterpret_cast<uintptr_t>(&shdr.sh_type) - reinterpret_cast<uintptr_t>(&shdr);
329 return false; 329 return false;
330 } 330 }
331 331
332 if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { 332 if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
333 if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
334 last_error_.code = ERROR_MEMORY_INVALID;
335 last_error_.address = offset;
336 return false;
337 }
338 // Need to go get the information about the section that contains 333 // Need to go get the information about the section that contains
339 // the string terminated names. 334 // the string terminated names.
340 ShdrType str_shdr; 335 ShdrType str_shdr;
@@ -343,39 +338,19 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
343 return false; 338 return false;
344 } 339 }
345 uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize; 340 uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
346 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) { 341 if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) {
347 last_error_.code = ERROR_MEMORY_INVALID; 342 last_error_.code = ERROR_MEMORY_INVALID;
348 last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_type) - 343 last_error_.address = str_offset;
349 reinterpret_cast<uintptr_t>(&str_shdr);
350 return false; 344 return false;
351 } 345 }
352 if (str_shdr.sh_type != SHT_STRTAB) { 346 if (str_shdr.sh_type != SHT_STRTAB) {
353 last_error_.code = ERROR_UNWIND_INFO; 347 last_error_.code = ERROR_UNWIND_INFO;
354 return false; 348 return false;
355 } 349 }
356 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset,
357 sizeof(str_shdr.sh_offset))) {
358 last_error_.code = ERROR_MEMORY_INVALID;
359 last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_offset) -
360 reinterpret_cast<uintptr_t>(&str_shdr);
361 return false;
362 }
363 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) {
364 last_error_.code = ERROR_MEMORY_INVALID;
365 last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_size) -
366 reinterpret_cast<uintptr_t>(&str_shdr);
367 return false;
368 }
369 symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize, 350 symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
370 str_shdr.sh_offset, str_shdr.sh_size)); 351 str_shdr.sh_offset, str_shdr.sh_size));
371 } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) { 352 } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
372 // Look for the .debug_frame and .gnu_debugdata. 353 // Look for the .debug_frame and .gnu_debugdata.
373 if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) {
374 last_error_.code = ERROR_MEMORY_INVALID;
375 last_error_.address = offset + reinterpret_cast<uintptr_t>(&shdr.sh_name) -
376 reinterpret_cast<uintptr_t>(&shdr);
377 return false;
378 }
379 if (shdr.sh_name < sec_size) { 354 if (shdr.sh_name < sec_size) {
380 std::string name; 355 std::string name;
381 if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) { 356 if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
@@ -394,14 +369,16 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
394 offset_ptr = &eh_frame_hdr_offset_; 369 offset_ptr = &eh_frame_hdr_offset_;
395 size_ptr = &eh_frame_hdr_size_; 370 size_ptr = &eh_frame_hdr_size_;
396 } 371 }
397 if (offset_ptr != nullptr && 372 if (offset_ptr != nullptr) {
398 memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
399 memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
400 *offset_ptr = shdr.sh_offset; 373 *offset_ptr = shdr.sh_offset;
401 *size_ptr = shdr.sh_size; 374 *size_ptr = shdr.sh_size;
402 } 375 }
403 } 376 }
404 } 377 }
378 } else if (shdr.sh_type == SHT_STRTAB) {
379 // In order to read soname, keep track of address to offset mapping.
380 strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr),
381 static_cast<uint64_t>(shdr.sh_offset)));
405 } 382 }
406 } 383 }
407 return true; 384 return true;
@@ -420,7 +397,7 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
420 soname_type_ = SONAME_INVALID; 397 soname_type_ = SONAME_INVALID;
421 398
422 uint64_t soname_offset = 0; 399 uint64_t soname_offset = 0;
423 uint64_t strtab_offset = 0; 400 uint64_t strtab_addr = 0;
424 uint64_t strtab_size = 0; 401 uint64_t strtab_size = 0;
425 402
426 // Find the soname location from the dynamic headers section. 403 // Find the soname location from the dynamic headers section.
@@ -435,7 +412,7 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
435 } 412 }
436 413
437 if (dyn.d_tag == DT_STRTAB) { 414 if (dyn.d_tag == DT_STRTAB) {
438 strtab_offset = dyn.d_un.d_ptr; 415 strtab_addr = dyn.d_un.d_ptr;
439 } else if (dyn.d_tag == DT_STRSZ) { 416 } else if (dyn.d_tag == DT_STRSZ) {
440 strtab_size = dyn.d_un.d_val; 417 strtab_size = dyn.d_un.d_val;
441 } else if (dyn.d_tag == DT_SONAME) { 418 } else if (dyn.d_tag == DT_SONAME) {
@@ -445,16 +422,22 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
445 } 422 }
446 } 423 }
447 424
448 soname_offset += strtab_offset; 425 // Need to map the strtab address to the real offset.
449 if (soname_offset >= strtab_offset + strtab_size) { 426 for (const auto& entry : strtabs_) {
450 return false; 427 if (entry.first == strtab_addr) {
451 } 428 soname_offset = entry.second + soname_offset;
452 if (!memory_->ReadString(soname_offset, &soname_)) { 429 if (soname_offset >= entry.second + strtab_size) {
453 return false; 430 return false;
431 }
432 if (!memory_->ReadString(soname_offset, &soname_)) {
433 return false;
434 }
435 soname_type_ = SONAME_VALID;
436 *soname = soname_;
437 return true;
438 }
454 } 439 }
455 soname_type_ = SONAME_VALID; 440 return false;
456 *soname = soname_;
457 return true;
458} 441}
459 442
460template <typename SymType> 443template <typename SymType>
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 0c153351d..39378a3af 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -117,23 +117,15 @@ Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gn
117 if (Elf::CachingEnabled() && !name.empty()) { 117 if (Elf::CachingEnabled() && !name.empty()) {
118 Elf::CacheLock(); 118 Elf::CacheLock();
119 locked = true; 119 locked = true;
120 if (offset != 0) { 120 if (Elf::CacheGet(this)) {
121 std::string hash(name + ':' + std::to_string(offset));
122 if (Elf::CacheGet(hash, &elf)) {
123 Elf::CacheUnlock();
124 return elf.get();
125 }
126 } else if (Elf::CacheGet(name, &elf)) {
127 Elf::CacheUnlock(); 121 Elf::CacheUnlock();
128 return elf.get(); 122 return elf.get();
129 } 123 }
130 } 124 }
131 125
132 Memory* memory = CreateMemory(process_memory); 126 Memory* memory = CreateMemory(process_memory);
133 if (locked && offset != 0 && elf_offset != 0) { 127 if (locked) {
134 // In this case, the whole file is the elf, need to see if the elf 128 if (Elf::CacheAfterCreateMemory(this)) {
135 // data was cached.
136 if (Elf::CacheGet(name, &elf)) {
137 delete memory; 129 delete memory;
138 Elf::CacheUnlock(); 130 Elf::CacheUnlock();
139 return elf.get(); 131 return elf.get();
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index 7f1614690..5502ce1fe 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -35,26 +35,25 @@ ArchEnum RegsArm::Arch() {
35 return ARCH_ARM; 35 return ARCH_ARM;
36} 36}
37 37
38uint64_t RegsArm::GetAdjustedPc(uint64_t rel_pc, Elf* elf) { 38uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 uint64_t load_bias = elf->GetLoadBias(); 39 uint64_t load_bias = elf->GetLoadBias();
40 if (rel_pc < load_bias) { 40 if (rel_pc < load_bias) {
41 return rel_pc; 41 return 0;
42 } 42 }
43 uint64_t adjusted_rel_pc = rel_pc - load_bias; 43 uint64_t adjusted_rel_pc = rel_pc - load_bias;
44
45 if (adjusted_rel_pc < 5) { 44 if (adjusted_rel_pc < 5) {
46 return rel_pc; 45 return 0;
47 } 46 }
48 47
49 if (adjusted_rel_pc & 1) { 48 if (adjusted_rel_pc & 1) {
50 // This is a thumb instruction, it could be 2 or 4 bytes. 49 // This is a thumb instruction, it could be 2 or 4 bytes.
51 uint32_t value; 50 uint32_t value;
52 if (rel_pc < 5 || !elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) || 51 if (!elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) ||
53 (value & 0xe000f000) != 0xe000f000) { 52 (value & 0xe000f000) != 0xe000f000) {
54 return rel_pc - 2; 53 return 2;
55 } 54 }
56 } 55 }
57 return rel_pc - 4; 56 return 4;
58} 57}
59 58
60void RegsArm::SetFromRaw() { 59void RegsArm::SetFromRaw() {
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index d6b467ade..cc6f5ce87 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -35,15 +35,11 @@ ArchEnum RegsArm64::Arch() {
35 return ARCH_ARM64; 35 return ARCH_ARM64;
36} 36}
37 37
38uint64_t RegsArm64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) { 38uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 if (!elf->valid()) { 39 if (!elf->valid() || rel_pc < 4) {
40 return rel_pc; 40 return 0;
41 } 41 }
42 42 return 4;
43 if (rel_pc < 4) {
44 return rel_pc;
45 }
46 return rel_pc - 4;
47} 43}
48 44
49void RegsArm64::SetFromRaw() { 45void RegsArm64::SetFromRaw() {
diff --git a/libunwindstack/RegsInfo.h b/libunwindstack/RegsInfo.h
new file mode 100644
index 000000000..47825f534
--- /dev/null
+++ b/libunwindstack/RegsInfo.h
@@ -0,0 +1,66 @@
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBUNWINDSTACK_REGS_INFO_H
18#define _LIBUNWINDSTACK_REGS_INFO_H
19
20#include <stdint.h>
21
22#include <unwindstack/Regs.h>
23
24namespace unwindstack {
25
26template <typename AddressType>
27struct RegsInfo {
28 RegsInfo(RegsImpl<AddressType>* regs) : regs(regs) {}
29
30 RegsImpl<AddressType>* regs = nullptr;
31 uint64_t saved_reg_map = 0;
32 AddressType saved_regs[64];
33
34 inline AddressType Get(uint32_t reg) {
35 if (IsSaved(reg)) {
36 return saved_regs[reg];
37 }
38 return (*regs)[reg];
39 }
40
41 inline AddressType* Save(uint32_t reg) {
42 if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
43 // This should never happen as since all currently supported
44 // architectures have the total number of registers < 64.
45 abort();
46 }
47 saved_reg_map |= 1 << reg;
48 saved_regs[reg] = (*regs)[reg];
49 return &(*regs)[reg];
50 }
51
52 inline bool IsSaved(uint32_t reg) {
53 if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
54 // This should never happen as since all currently supported
55 // architectures have the total number of registers < 64.
56 abort();
57 }
58 return saved_reg_map & (1 << reg);
59 }
60
61 inline uint16_t Total() { return regs->total_regs(); }
62};
63
64} // namespace unwindstack
65
66#endif // _LIBUNWINDSTACK_REGS_INFO_H
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index 6751f52dd..5d20bef4a 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -35,16 +35,12 @@ ArchEnum RegsMips::Arch() {
35 return ARCH_MIPS; 35 return ARCH_MIPS;
36} 36}
37 37
38uint64_t RegsMips::GetAdjustedPc(uint64_t rel_pc, Elf* elf) { 38uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 if (!elf->valid()) { 39 if (!elf->valid() || rel_pc < 8) {
40 return rel_pc; 40 return 0;
41 } 41 }
42 42 // For now, just assume no compact branches
43 // For now, just assuming no compact branches 43 return 8;
44 if (rel_pc < 8) {
45 return rel_pc;
46 }
47 return rel_pc - 8;
48} 44}
49 45
50void RegsMips::SetFromRaw() { 46void RegsMips::SetFromRaw() {
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index 97082bd9d..4a03538e2 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -36,16 +36,12 @@ ArchEnum RegsMips64::Arch() {
36 return ARCH_MIPS64; 36 return ARCH_MIPS64;
37} 37}
38 38
39uint64_t RegsMips64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) { 39uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
40 if (!elf->valid()) { 40 if (!elf->valid() || rel_pc < 8) {
41 return rel_pc; 41 return 0;
42 } 42 }
43 43 // For now, just assume no compact branches
44 // For now, just assuming no compact branches 44 return 8;
45 if (rel_pc < 8) {
46 return rel_pc;
47 }
48 return rel_pc - 8;
49} 45}
50 46
51void RegsMips64::SetFromRaw() { 47void RegsMips64::SetFromRaw() {
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
index 27476b7cb..573cb2382 100644
--- a/libunwindstack/RegsX86.cpp
+++ b/libunwindstack/RegsX86.cpp
@@ -35,15 +35,11 @@ ArchEnum RegsX86::Arch() {
35 return ARCH_X86; 35 return ARCH_X86;
36} 36}
37 37
38uint64_t RegsX86::GetAdjustedPc(uint64_t rel_pc, Elf* elf) { 38uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 if (!elf->valid()) { 39 if (!elf->valid() || rel_pc == 0) {
40 return rel_pc;
41 }
42
43 if (rel_pc == 0) {
44 return 0; 40 return 0;
45 } 41 }
46 return rel_pc - 1; 42 return 1;
47} 43}
48 44
49void RegsX86::SetFromRaw() { 45void RegsX86::SetFromRaw() {
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index 0f66943aa..3175a90c2 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -35,16 +35,11 @@ ArchEnum RegsX86_64::Arch() {
35 return ARCH_X86_64; 35 return ARCH_X86_64;
36} 36}
37 37
38uint64_t RegsX86_64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) { 38uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
39 if (!elf->valid()) { 39 if (!elf->valid() || rel_pc == 0) {
40 return rel_pc;
41 }
42
43 if (rel_pc == 0) {
44 return 0; 40 return 0;
45 } 41 }
46 42 return 1;
47 return rel_pc - 1;
48} 43}
49 44
50void RegsX86_64::SetFromRaw() { 45void RegsX86_64::SetFromRaw() {
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 5e3293325..7da699441 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -48,6 +48,7 @@ void Unwinder::FillInDexFrame() {
48 size_t frame_num = frames_.size(); 48 size_t frame_num = frames_.size();
49 frames_.resize(frame_num + 1); 49 frames_.resize(frame_num + 1);
50 FrameData* frame = &frames_.at(frame_num); 50 FrameData* frame = &frames_.at(frame_num);
51 frame->num = frame_num;
51 52
52 uint64_t dex_pc = regs_->dex_pc(); 53 uint64_t dex_pc = regs_->dex_pc();
53 frame->pc = dex_pc; 54 frame->pc = dex_pc;
@@ -67,6 +68,10 @@ void Unwinder::FillInDexFrame() {
67 return; 68 return;
68 } 69 }
69 70
71 if (!resolve_names_) {
72 return;
73 }
74
70#if !defined(NO_LIBDEXFILE_SUPPORT) 75#if !defined(NO_LIBDEXFILE_SUPPORT)
71 if (dex_files_ == nullptr) { 76 if (dex_files_ == nullptr) {
72 return; 77 return;
@@ -78,20 +83,20 @@ void Unwinder::FillInDexFrame() {
78#endif 83#endif
79} 84}
80 85
81void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc, uint64_t func_pc) { 86void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc,
87 uint64_t pc_adjustment) {
82 size_t frame_num = frames_.size(); 88 size_t frame_num = frames_.size();
83 frames_.resize(frame_num + 1); 89 frames_.resize(frame_num + 1);
84 FrameData* frame = &frames_.at(frame_num); 90 FrameData* frame = &frames_.at(frame_num);
85 frame->num = frame_num; 91 frame->num = frame_num;
86 frame->sp = regs_->sp(); 92 frame->sp = regs_->sp();
87 frame->rel_pc = adjusted_rel_pc; 93 frame->rel_pc = rel_pc - pc_adjustment;
94 frame->pc = regs_->pc() - pc_adjustment;
88 95
89 if (map_info == nullptr) { 96 if (map_info == nullptr) {
90 frame->pc = regs_->pc();
91 return; 97 return;
92 } 98 }
93 99
94 frame->pc = map_info->start + adjusted_rel_pc - elf->GetLoadBias() - map_info->elf_offset;
95 frame->map_name = map_info->name; 100 frame->map_name = map_info->name;
96 frame->map_offset = map_info->offset; 101 frame->map_offset = map_info->offset;
97 frame->map_start = map_info->start; 102 frame->map_start = map_info->start;
@@ -99,7 +104,8 @@ void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc
99 frame->map_flags = map_info->flags; 104 frame->map_flags = map_info->flags;
100 frame->map_load_bias = elf->GetLoadBias(); 105 frame->map_load_bias = elf->GetLoadBias();
101 106
102 if (!elf->GetFunctionName(func_pc, &frame->function_name, &frame->function_offset)) { 107 if (!resolve_names_ ||
108 !elf->GetFunctionName(func_pc, &frame->function_name, &frame->function_offset)) {
103 frame->function_name = ""; 109 frame->function_name = "";
104 frame->function_offset = 0; 110 frame->function_offset = 0;
105 } 111 }
@@ -134,13 +140,12 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
134 140
135 MapInfo* map_info = maps_->Find(regs_->pc()); 141 MapInfo* map_info = maps_->Find(regs_->pc());
136 uint64_t rel_pc; 142 uint64_t rel_pc;
137 uint64_t adjusted_pc; 143 uint64_t pc_adjustment = 0;
138 uint64_t adjusted_rel_pc; 144 uint64_t step_pc;
139 Elf* elf; 145 Elf* elf;
140 if (map_info == nullptr) { 146 if (map_info == nullptr) {
141 rel_pc = regs_->pc(); 147 rel_pc = regs_->pc();
142 adjusted_rel_pc = rel_pc; 148 step_pc = rel_pc;
143 adjusted_pc = rel_pc;
144 last_error_.code = ERROR_INVALID_MAP; 149 last_error_.code = ERROR_INVALID_MAP;
145 } else { 150 } else {
146 if (ShouldStop(map_suffixes_to_ignore, map_info->name)) { 151 if (ShouldStop(map_suffixes_to_ignore, map_info->name)) {
@@ -149,21 +154,20 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
149 elf = map_info->GetElf(process_memory_, true); 154 elf = map_info->GetElf(process_memory_, true);
150 rel_pc = elf->GetRelPc(regs_->pc(), map_info); 155 rel_pc = elf->GetRelPc(regs_->pc(), map_info);
151 if (adjust_pc) { 156 if (adjust_pc) {
152 adjusted_pc = regs_->GetAdjustedPc(rel_pc, elf); 157 pc_adjustment = regs_->GetPcAdjustment(rel_pc, elf);
153 } else { 158 } else {
154 adjusted_pc = rel_pc; 159 pc_adjustment = 0;
155 } 160 }
156 adjusted_rel_pc = adjusted_pc; 161 step_pc = rel_pc - pc_adjustment;
157 162
158 // If the pc is in an invalid elf file, try and get an Elf object 163 // If the pc is in an invalid elf file, try and get an Elf object
159 // using the jit debug information. 164 // using the jit debug information.
160 if (!elf->valid() && jit_debug_ != nullptr) { 165 if (!elf->valid() && jit_debug_ != nullptr) {
161 uint64_t adjusted_jit_pc = regs_->pc() - (rel_pc - adjusted_pc); 166 uint64_t adjusted_jit_pc = regs_->pc() - pc_adjustment;
162 Elf* jit_elf = jit_debug_->GetElf(maps_, adjusted_jit_pc); 167 Elf* jit_elf = jit_debug_->GetElf(maps_, adjusted_jit_pc);
163 if (jit_elf != nullptr) { 168 if (jit_elf != nullptr) {
164 // The jit debug information requires a non relative adjusted pc. 169 // The jit debug information requires a non relative adjusted pc.
165 adjusted_pc = adjusted_jit_pc; 170 step_pc = adjusted_jit_pc;
166 adjusted_rel_pc = adjusted_pc - map_info->start;
167 elf = jit_elf; 171 elf = jit_elf;
168 } 172 }
169 } 173 }
@@ -179,7 +183,7 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
179 regs_->set_dex_pc(0); 183 regs_->set_dex_pc(0);
180 } 184 }
181 185
182 FillInFrame(map_info, elf, adjusted_rel_pc, adjusted_pc); 186 FillInFrame(map_info, elf, rel_pc, step_pc, pc_adjustment);
183 187
184 // Once a frame is added, stop skipping frames. 188 // Once a frame is added, stop skipping frames.
185 initial_map_names_to_skip = nullptr; 189 initial_map_names_to_skip = nullptr;
@@ -207,8 +211,8 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
207 in_device_map = true; 211 in_device_map = true;
208 } else { 212 } else {
209 bool finished; 213 bool finished;
210 stepped = elf->Step(rel_pc, adjusted_pc, map_info->elf_offset, regs_, 214 stepped = elf->Step(rel_pc, step_pc, map_info->elf_offset, regs_, process_memory_.get(),
211 process_memory_.get(), &finished); 215 &finished);
212 elf->GetLastError(&last_error_); 216 elf->GetLastError(&last_error_);
213 if (stepped && finished) { 217 if (stepped && finished) {
214 break; 218 break;
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index 03f40d699..da91fd087 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -32,6 +32,8 @@ namespace unwindstack {
32// Forward declarations. 32// Forward declarations.
33class Memory; 33class Memory;
34class Regs; 34class Regs;
35template <typename AddressType>
36struct RegsInfo;
35 37
36class DwarfSection { 38class DwarfSection {
37 public: 39 public:
@@ -149,8 +151,8 @@ class DwarfSectionImpl : public DwarfSection {
149 bool Log(uint8_t indent, uint64_t pc, uint64_t load_bias, const DwarfFde* fde) override; 151 bool Log(uint8_t indent, uint64_t pc, uint64_t load_bias, const DwarfFde* fde) override;
150 152
151 protected: 153 protected:
152 bool EvalExpression(const DwarfLocation& loc, uint8_t version, Memory* regular_memory, 154 bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
153 AddressType* value); 155 RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
154 156
155 bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding); 157 bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding);
156 158
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index a874709d2..385973e9f 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -23,6 +23,7 @@
23#include <mutex> 23#include <mutex>
24#include <string> 24#include <string>
25#include <unordered_map> 25#include <unordered_map>
26#include <utility>
26 27
27#include <unwindstack/ElfInterface.h> 28#include <unwindstack/ElfInterface.h>
28#include <unwindstack/Memory.h> 29#include <unwindstack/Memory.h>
@@ -103,7 +104,8 @@ class Elf {
103 static void CacheLock(); 104 static void CacheLock();
104 static void CacheUnlock(); 105 static void CacheUnlock();
105 static void CacheAdd(MapInfo* info); 106 static void CacheAdd(MapInfo* info);
106 static bool CacheGet(const std::string& name, std::shared_ptr<Elf>* elf); 107 static bool CacheGet(MapInfo* info);
108 static bool CacheAfterCreateMemory(MapInfo* info);
107 109
108 protected: 110 protected:
109 bool valid_ = false; 111 bool valid_ = false;
@@ -120,7 +122,7 @@ class Elf {
120 std::unique_ptr<ElfInterface> gnu_debugdata_interface_; 122 std::unique_ptr<ElfInterface> gnu_debugdata_interface_;
121 123
122 static bool cache_enabled_; 124 static bool cache_enabled_;
123 static std::unordered_map<std::string, std::shared_ptr<Elf>>* cache_; 125 static std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* cache_;
124 static std::mutex* cache_lock_; 126 static std::mutex* cache_lock_;
125}; 127};
126 128
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index ea9ec9dac..3a221bc2e 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -157,6 +157,7 @@ class ElfInterface {
157 ElfInterface* gnu_debugdata_interface_ = nullptr; 157 ElfInterface* gnu_debugdata_interface_ = nullptr;
158 158
159 std::vector<Symbols*> symbols_; 159 std::vector<Symbols*> symbols_;
160 std::vector<std::pair<uint64_t, uint64_t>> strtabs_;
160}; 161};
161 162
162class ElfInterface32 : public ElfInterface { 163class ElfInterface32 : public ElfInterface {
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index a5ba7a078..b0e7ea152 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -60,7 +60,7 @@ class Regs {
60 uint64_t dex_pc() { return dex_pc_; } 60 uint64_t dex_pc() { return dex_pc_; }
61 void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; } 61 void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
62 62
63 virtual uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) = 0; 63 virtual uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) = 0;
64 64
65 virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0; 65 virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0;
66 66
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
index b5d344be6..5af90d3f5 100644
--- a/libunwindstack/include/unwindstack/RegsArm.h
+++ b/libunwindstack/include/unwindstack/RegsArm.h
@@ -36,7 +36,7 @@ class RegsArm : public RegsImpl<uint32_t> {
36 36
37 virtual ArchEnum Arch() override final; 37 virtual ArchEnum Arch() override final;
38 38
39 uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override; 39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
40 40
41 void SetFromRaw() override; 41 void SetFromRaw() override;
42 42
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
index 30e626ccf..cb05732ee 100644
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -36,7 +36,7 @@ class RegsArm64 : public RegsImpl<uint64_t> {
36 36
37 virtual ArchEnum Arch() override final; 37 virtual ArchEnum Arch() override final;
38 38
39 uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override; 39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
40 40
41 void SetFromRaw() override; 41 void SetFromRaw() override;
42 42
diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h
index 3fe6a9f7f..8e3c01f20 100644
--- a/libunwindstack/include/unwindstack/RegsMips.h
+++ b/libunwindstack/include/unwindstack/RegsMips.h
@@ -36,7 +36,7 @@ class RegsMips : public RegsImpl<uint32_t> {
36 36
37 virtual ArchEnum Arch() override final; 37 virtual ArchEnum Arch() override final;
38 38
39 uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override; 39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
40 40
41 void SetFromRaw() override; 41 void SetFromRaw() override;
42 42
diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h
index 6b4bcdf92..8c2d4437f 100644
--- a/libunwindstack/include/unwindstack/RegsMips64.h
+++ b/libunwindstack/include/unwindstack/RegsMips64.h
@@ -36,7 +36,7 @@ class RegsMips64 : public RegsImpl<uint64_t> {
36 36
37 virtual ArchEnum Arch() override final; 37 virtual ArchEnum Arch() override final;
38 38
39 uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override; 39 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
40 40
41 void SetFromRaw() override; 41 void SetFromRaw() override;
42 42
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
index a695bbfbb..1bc145d97 100644
--- a/libunwindstack/include/unwindstack/RegsX86.h
+++ b/libunwindstack/include/unwindstack/RegsX86.h
@@ -37,7 +37,7 @@ class RegsX86 : public RegsImpl<uint32_t> {
37 37
38 virtual ArchEnum Arch() override final; 38 virtual ArchEnum Arch() override final;
39 39
40 uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override; 40 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
41 41
42 void SetFromRaw() override; 42 void SetFromRaw() override;
43 43
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
index 23a3f2077..4cd45d4b9 100644
--- a/libunwindstack/include/unwindstack/RegsX86_64.h
+++ b/libunwindstack/include/unwindstack/RegsX86_64.h
@@ -37,7 +37,7 @@ class RegsX86_64 : public RegsImpl<uint64_t> {
37 37
38 virtual ArchEnum Arch() override final; 38 virtual ArchEnum Arch() override final;
39 39
40 uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override; 40 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
41 41
42 void SetFromRaw() override; 42 void SetFromRaw() override;
43 43
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index ebe7b0a5d..56b058156 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -75,6 +75,10 @@ class Unwinder {
75 75
76 void SetJitDebug(JitDebug* jit_debug, ArchEnum arch); 76 void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
77 77
78 // Disabling the resolving of names results in the function name being
79 // set to an empty string and the function offset being set to zero.
80 void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
81
78#if !defined(NO_LIBDEXFILE_SUPPORT) 82#if !defined(NO_LIBDEXFILE_SUPPORT)
79 void SetDexFiles(DexFiles* dex_files, ArchEnum arch); 83 void SetDexFiles(DexFiles* dex_files, ArchEnum arch);
80#endif 84#endif
@@ -84,7 +88,8 @@ class Unwinder {
84 88
85 private: 89 private:
86 void FillInDexFrame(); 90 void FillInDexFrame();
87 void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc, uint64_t adjusted_pc); 91 void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc,
92 uint64_t pc_adjustment);
88 93
89 size_t max_frames_; 94 size_t max_frames_;
90 Maps* maps_; 95 Maps* maps_;
@@ -95,6 +100,7 @@ class Unwinder {
95#if !defined(NO_LIBDEXFILE_SUPPORT) 100#if !defined(NO_LIBDEXFILE_SUPPORT)
96 DexFiles* dex_files_ = nullptr; 101 DexFiles* dex_files_ = nullptr;
97#endif 102#endif
103 bool resolve_names_ = true;
98 ErrorData last_error_; 104 ErrorData last_error_;
99}; 105};
100 106
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index dca560549..d029bb088 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -63,7 +63,7 @@ class DexFilesTest : public ::testing::Test {
63 elf->FakeSetValid(true); 63 elf->FakeSetValid(true);
64 ElfInterfaceFake* interface = new ElfInterfaceFake(memory); 64 ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
65 elf->FakeSetInterface(interface); 65 elf->FakeSetInterface(interface);
66 interface->FakeSetGlobalVariable("__art_debug_dexfiles", 0x800); 66 interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
67 map_info->elf.reset(elf); 67 map_info->elf.reset(elf);
68 68
69 // Global variable not set by default. 69 // Global variable not set by default.
@@ -74,7 +74,7 @@ class DexFilesTest : public ::testing::Test {
74 elf->FakeSetValid(true); 74 elf->FakeSetValid(true);
75 interface = new ElfInterfaceFake(memory); 75 interface = new ElfInterfaceFake(memory);
76 elf->FakeSetInterface(interface); 76 elf->FakeSetInterface(interface);
77 interface->FakeSetGlobalVariable("__art_debug_dexfiles", 0x800); 77 interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
78 map_info->elf.reset(elf); 78 map_info->elf.reset(elf);
79 79
80 // Global variable set in this map. 80 // Global variable set in this map.
@@ -85,10 +85,12 @@ class DexFilesTest : public ::testing::Test {
85 elf->FakeSetValid(true); 85 elf->FakeSetValid(true);
86 interface = new ElfInterfaceFake(memory); 86 interface = new ElfInterfaceFake(memory);
87 elf->FakeSetInterface(interface); 87 elf->FakeSetInterface(interface);
88 interface->FakeSetGlobalVariable("__art_debug_dexfiles", 0x800); 88 interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
89 map_info->elf.reset(elf); 89 map_info->elf.reset(elf);
90 } 90 }
91 91
92 void WriteDescriptor32(uint64_t addr, uint32_t head);
93 void WriteDescriptor64(uint64_t addr, uint64_t head);
92 void WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, uint32_t dex_file); 94 void WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, uint32_t dex_file);
93 void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file); 95 void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file);
94 void WriteDex(uint64_t dex_file); 96 void WriteDex(uint64_t dex_file);
@@ -105,6 +107,16 @@ class DexFilesTest : public ::testing::Test {
105 std::unique_ptr<BufferMaps> maps_; 107 std::unique_ptr<BufferMaps> maps_;
106}; 108};
107 109
110void DexFilesTest::WriteDescriptor32(uint64_t addr, uint32_t head) {
111 // void* first_entry_
112 memory_->SetData32(addr + 12, head);
113}
114
115void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t head) {
116 // void* first_entry_
117 memory_->SetData64(addr + 16, head);
118}
119
108void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, 120void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev,
109 uint32_t dex_file) { 121 uint32_t dex_file) {
110 // Format of the 32 bit DEXFileEntry structure: 122 // Format of the 32 bit DEXFileEntry structure:
@@ -146,7 +158,7 @@ TEST_F(DexFilesTest, get_method_information_32) {
146 uint64_t method_offset = 0x124; 158 uint64_t method_offset = 0x124;
147 MapInfo* info = maps_->Get(kMapDexFiles); 159 MapInfo* info = maps_->Get(kMapDexFiles);
148 160
149 memory_->SetData32(0xf800, 0x200000); 161 WriteDescriptor32(0xf800, 0x200000);
150 WriteEntry32(0x200000, 0, 0, 0x300000); 162 WriteEntry32(0x200000, 0, 0, 0x300000);
151 WriteDex(0x300000); 163 WriteDex(0x300000);
152 164
@@ -161,7 +173,7 @@ TEST_F(DexFilesTest, get_method_information_64) {
161 MapInfo* info = maps_->Get(kMapDexFiles); 173 MapInfo* info = maps_->Get(kMapDexFiles);
162 174
163 dex_files_->SetArch(ARCH_ARM64); 175 dex_files_->SetArch(ARCH_ARM64);
164 memory_->SetData64(0xf800, 0x200000); 176 WriteDescriptor64(0xf800, 0x200000);
165 WriteEntry64(0x200000, 0, 0, 0x301000); 177 WriteEntry64(0x200000, 0, 0, 0x301000);
166 WriteDex(0x301000); 178 WriteDex(0x301000);
167 179
@@ -175,7 +187,7 @@ TEST_F(DexFilesTest, get_method_information_not_first_entry_32) {
175 uint64_t method_offset = 0x124; 187 uint64_t method_offset = 0x124;
176 MapInfo* info = maps_->Get(kMapDexFiles); 188 MapInfo* info = maps_->Get(kMapDexFiles);
177 189
178 memory_->SetData32(0xf800, 0x200000); 190 WriteDescriptor32(0xf800, 0x200000);
179 WriteEntry32(0x200000, 0x200100, 0, 0x100000); 191 WriteEntry32(0x200000, 0x200100, 0, 0x100000);
180 WriteEntry32(0x200100, 0, 0x200000, 0x300000); 192 WriteEntry32(0x200100, 0, 0x200000, 0x300000);
181 WriteDex(0x300000); 193 WriteDex(0x300000);
@@ -191,7 +203,7 @@ TEST_F(DexFilesTest, get_method_information_not_first_entry_64) {
191 MapInfo* info = maps_->Get(kMapDexFiles); 203 MapInfo* info = maps_->Get(kMapDexFiles);
192 204
193 dex_files_->SetArch(ARCH_ARM64); 205 dex_files_->SetArch(ARCH_ARM64);
194 memory_->SetData64(0xf800, 0x200000); 206 WriteDescriptor64(0xf800, 0x200000);
195 WriteEntry64(0x200000, 0x200100, 0, 0x100000); 207 WriteEntry64(0x200000, 0x200100, 0, 0x100000);
196 WriteEntry64(0x200100, 0, 0x200000, 0x300000); 208 WriteEntry64(0x200100, 0, 0x200000, 0x300000);
197 WriteDex(0x300000); 209 WriteDex(0x300000);
@@ -206,7 +218,7 @@ TEST_F(DexFilesTest, get_method_information_cached) {
206 uint64_t method_offset = 0x124; 218 uint64_t method_offset = 0x124;
207 MapInfo* info = maps_->Get(kMapDexFiles); 219 MapInfo* info = maps_->Get(kMapDexFiles);
208 220
209 memory_->SetData32(0xf800, 0x200000); 221 WriteDescriptor32(0xf800, 0x200000);
210 WriteEntry32(0x200000, 0, 0, 0x300000); 222 WriteEntry32(0x200000, 0, 0, 0x300000);
211 WriteDex(0x300000); 223 WriteDex(0x300000);
212 224
@@ -226,7 +238,7 @@ TEST_F(DexFilesTest, get_method_information_search_libs) {
226 uint64_t method_offset = 0x124; 238 uint64_t method_offset = 0x124;
227 MapInfo* info = maps_->Get(kMapDexFiles); 239 MapInfo* info = maps_->Get(kMapDexFiles);
228 240
229 memory_->SetData32(0xf800, 0x200000); 241 WriteDescriptor32(0xf800, 0x200000);
230 WriteEntry32(0x200000, 0x200100, 0, 0x100000); 242 WriteEntry32(0x200000, 0x200100, 0, 0x100000);
231 WriteEntry32(0x200100, 0, 0x200000, 0x300000); 243 WriteEntry32(0x200100, 0, 0x200000, 0x300000);
232 WriteDex(0x300000); 244 WriteDex(0x300000);
@@ -259,9 +271,9 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
259 MapInfo* info = maps_->Get(kMapDexFiles); 271 MapInfo* info = maps_->Get(kMapDexFiles);
260 272
261 // First global variable found, but value is zero. 273 // First global variable found, but value is zero.
262 memory_->SetData32(0xc800, 0); 274 WriteDescriptor32(0xc800, 0);
263 275
264 memory_->SetData32(0xf800, 0x200000); 276 WriteDescriptor32(0xf800, 0x200000);
265 WriteEntry32(0x200000, 0, 0, 0x300000); 277 WriteEntry32(0x200000, 0, 0, 0x300000);
266 WriteDex(0x300000); 278 WriteDex(0x300000);
267 279
@@ -274,7 +286,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
274 dex_files_->SetArch(ARCH_ARM); 286 dex_files_->SetArch(ARCH_ARM);
275 method_name = "fail"; 287 method_name = "fail";
276 method_offset = 0x123; 288 method_offset = 0x123;
277 memory_->SetData32(0xc800, 0x100000); 289 WriteDescriptor32(0xc800, 0x100000);
278 dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); 290 dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
279 EXPECT_EQ("fail", method_name); 291 EXPECT_EQ("fail", method_name);
280 EXPECT_EQ(0x123U, method_offset); 292 EXPECT_EQ(0x123U, method_offset);
@@ -286,9 +298,9 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
286 MapInfo* info = maps_->Get(kMapDexFiles); 298 MapInfo* info = maps_->Get(kMapDexFiles);
287 299
288 // First global variable found, but value is zero. 300 // First global variable found, but value is zero.
289 memory_->SetData64(0xc800, 0); 301 WriteDescriptor64(0xc800, 0);
290 302
291 memory_->SetData64(0xf800, 0x200000); 303 WriteDescriptor64(0xf800, 0x200000);
292 WriteEntry64(0x200000, 0, 0, 0x300000); 304 WriteEntry64(0x200000, 0, 0, 0x300000);
293 WriteDex(0x300000); 305 WriteDex(0x300000);
294 306
@@ -302,7 +314,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
302 dex_files_->SetArch(ARCH_ARM64); 314 dex_files_->SetArch(ARCH_ARM64);
303 method_name = "fail"; 315 method_name = "fail";
304 method_offset = 0x123; 316 method_offset = 0x123;
305 memory_->SetData32(0xc800, 0x100000); 317 WriteDescriptor64(0xc800, 0x100000);
306 dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); 318 dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
307 EXPECT_EQ("fail", method_name); 319 EXPECT_EQ("fail", method_name);
308 EXPECT_EQ(0x123U, method_offset); 320 EXPECT_EQ(0x123U, method_offset);
diff --git a/libunwindstack/tests/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp
index 036226d03..6e15227b3 100644
--- a/libunwindstack/tests/DwarfOpTest.cpp
+++ b/libunwindstack/tests/DwarfOpTest.cpp
@@ -52,14 +52,14 @@ TYPED_TEST_CASE_P(DwarfOpTest);
52 52
53TYPED_TEST_P(DwarfOpTest, decode) { 53TYPED_TEST_P(DwarfOpTest, decode) {
54 // Memory error. 54 // Memory error.
55 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 55 ASSERT_FALSE(this->op_->Decode());
56 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode()); 56 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
57 EXPECT_EQ(0U, this->op_->LastErrorAddress()); 57 EXPECT_EQ(0U, this->op_->LastErrorAddress());
58 58
59 // No error. 59 // No error.
60 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96}); 60 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96});
61 this->mem_->set_cur_offset(0); 61 this->mem_->set_cur_offset(0);
62 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 62 ASSERT_TRUE(this->op_->Decode());
63 ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode()); 63 ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode());
64 ASSERT_EQ(0x96U, this->op_->cur_op()); 64 ASSERT_EQ(0x96U, this->op_->cur_op());
65 ASSERT_EQ(1U, this->mem_->cur_offset()); 65 ASSERT_EQ(1U, this->mem_->cur_offset());
@@ -67,14 +67,14 @@ TYPED_TEST_P(DwarfOpTest, decode) {
67 67
68TYPED_TEST_P(DwarfOpTest, eval) { 68TYPED_TEST_P(DwarfOpTest, eval) {
69 // Memory error. 69 // Memory error.
70 ASSERT_FALSE(this->op_->Eval(0, 2, DWARF_VERSION_MAX)); 70 ASSERT_FALSE(this->op_->Eval(0, 2));
71 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode()); 71 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
72 EXPECT_EQ(0U, this->op_->LastErrorAddress()); 72 EXPECT_EQ(0U, this->op_->LastErrorAddress());
73 73
74 // Register set. 74 // Register set.
75 // Do this first, to verify that subsequent calls reset the value. 75 // Do this first, to verify that subsequent calls reset the value.
76 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x50}); 76 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x50});
77 ASSERT_TRUE(this->op_->Eval(0, 1, DWARF_VERSION_MAX)); 77 ASSERT_TRUE(this->op_->Eval(0, 1));
78 ASSERT_TRUE(this->op_->is_register()); 78 ASSERT_TRUE(this->op_->is_register());
79 ASSERT_EQ(1U, this->mem_->cur_offset()); 79 ASSERT_EQ(1U, this->mem_->cur_offset());
80 ASSERT_EQ(1U, this->op_->StackSize()); 80 ASSERT_EQ(1U, this->op_->StackSize());
@@ -85,7 +85,7 @@ TYPED_TEST_P(DwarfOpTest, eval) {
85 }; 85 };
86 this->op_memory_.SetMemory(0, opcode_buffer); 86 this->op_memory_.SetMemory(0, opcode_buffer);
87 87
88 ASSERT_TRUE(this->op_->Eval(0, 8, DWARF_VERSION_MAX)); 88 ASSERT_TRUE(this->op_->Eval(0, 8));
89 ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode()); 89 ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode());
90 ASSERT_FALSE(this->op_->is_register()); 90 ASSERT_FALSE(this->op_->is_register());
91 ASSERT_EQ(8U, this->mem_->cur_offset()); 91 ASSERT_EQ(8U, this->mem_->cur_offset());
@@ -97,7 +97,7 @@ TYPED_TEST_P(DwarfOpTest, eval) {
97 97
98 // Infinite loop. 98 // Infinite loop.
99 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x2f, 0xfd, 0xff}); 99 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x2f, 0xfd, 0xff});
100 ASSERT_FALSE(this->op_->Eval(0, 4, DWARF_VERSION_MAX)); 100 ASSERT_FALSE(this->op_->Eval(0, 4));
101 ASSERT_EQ(DWARF_ERROR_TOO_MANY_ITERATIONS, this->op_->LastErrorCode()); 101 ASSERT_EQ(DWARF_ERROR_TOO_MANY_ITERATIONS, this->op_->LastErrorCode());
102 ASSERT_FALSE(this->op_->is_register()); 102 ASSERT_FALSE(this->op_->is_register());
103 ASSERT_EQ(0U, this->op_->StackSize()); 103 ASSERT_EQ(0U, this->op_->StackSize());
@@ -112,29 +112,7 @@ TYPED_TEST_P(DwarfOpTest, illegal_opcode) {
112 this->op_memory_.SetMemory(0, opcode_buffer); 112 this->op_memory_.SetMemory(0, opcode_buffer);
113 113
114 for (size_t i = 0; i < opcode_buffer.size(); i++) { 114 for (size_t i = 0; i < opcode_buffer.size(); i++) {
115 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 115 ASSERT_FALSE(this->op_->Decode());
116 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
117 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
118 }
119}
120
121TYPED_TEST_P(DwarfOpTest, illegal_in_version3) {
122 std::vector<uint8_t> opcode_buffer = {0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d};
123 this->op_memory_.SetMemory(0, opcode_buffer);
124
125 for (size_t i = 0; i < opcode_buffer.size(); i++) {
126 ASSERT_FALSE(this->op_->Decode(2));
127 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
128 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
129 }
130}
131
132TYPED_TEST_P(DwarfOpTest, illegal_in_version4) {
133 std::vector<uint8_t> opcode_buffer = {0x9e, 0x9f};
134 this->op_memory_.SetMemory(0, opcode_buffer);
135
136 for (size_t i = 0; i < opcode_buffer.size(); i++) {
137 ASSERT_FALSE(this->op_->Decode(3));
138 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); 116 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
139 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op()); 117 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
140 } 118 }
@@ -174,12 +152,12 @@ TYPED_TEST_P(DwarfOpTest, not_implemented) {
174 this->op_memory_.SetMemory(0, opcode_buffer); 152 this->op_memory_.SetMemory(0, opcode_buffer);
175 153
176 // Push the stack values. 154 // Push the stack values.
177 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 155 ASSERT_TRUE(this->op_->Decode());
178 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 156 ASSERT_TRUE(this->op_->Decode());
179 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 157 ASSERT_TRUE(this->op_->Decode());
180 158
181 while (this->mem_->cur_offset() < opcode_buffer.size()) { 159 while (this->mem_->cur_offset() < opcode_buffer.size()) {
182 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 160 ASSERT_FALSE(this->op_->Decode());
183 ASSERT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->op_->LastErrorCode()); 161 ASSERT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->op_->LastErrorCode());
184 } 162 }
185} 163}
@@ -194,7 +172,7 @@ TYPED_TEST_P(DwarfOpTest, op_addr) {
194 } 172 }
195 this->op_memory_.SetMemory(0, opcode_buffer); 173 this->op_memory_.SetMemory(0, opcode_buffer);
196 174
197 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 175 ASSERT_TRUE(this->op_->Decode());
198 ASSERT_EQ(0x03, this->op_->cur_op()); 176 ASSERT_EQ(0x03, this->op_->cur_op());
199 ASSERT_EQ(1U, this->op_->StackSize()); 177 ASSERT_EQ(1U, this->op_->StackSize());
200 if (sizeof(TypeParam) == 4) { 178 if (sizeof(TypeParam) == 4) {
@@ -217,17 +195,17 @@ TYPED_TEST_P(DwarfOpTest, op_deref) {
217 TypeParam value = 0x12345678; 195 TypeParam value = 0x12345678;
218 this->regular_memory_.SetMemory(0x2010, &value, sizeof(value)); 196 this->regular_memory_.SetMemory(0x2010, &value, sizeof(value));
219 197
220 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 198 ASSERT_FALSE(this->op_->Decode());
221 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 199 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
222 200
223 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 201 ASSERT_TRUE(this->op_->Decode());
224 ASSERT_EQ(1U, this->op_->StackSize()); 202 ASSERT_EQ(1U, this->op_->StackSize());
225 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 203 ASSERT_TRUE(this->op_->Decode());
226 ASSERT_EQ(0x06, this->op_->cur_op()); 204 ASSERT_EQ(0x06, this->op_->cur_op());
227 ASSERT_EQ(1U, this->op_->StackSize()); 205 ASSERT_EQ(1U, this->op_->StackSize());
228 ASSERT_EQ(value, this->op_->StackAt(0)); 206 ASSERT_EQ(value, this->op_->StackAt(0));
229 207
230 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 208 ASSERT_FALSE(this->op_->Decode());
231 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode()); 209 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
232 ASSERT_EQ(0x12345678U, this->op_->LastErrorAddress()); 210 ASSERT_EQ(0x12345678U, this->op_->LastErrorAddress());
233} 211}
@@ -237,14 +215,14 @@ TYPED_TEST_P(DwarfOpTest, op_deref_size) {
237 TypeParam value = 0x12345678; 215 TypeParam value = 0x12345678;
238 this->regular_memory_.SetMemory(0x2010, &value, sizeof(value)); 216 this->regular_memory_.SetMemory(0x2010, &value, sizeof(value));
239 217
240 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 218 ASSERT_FALSE(this->op_->Decode());
241 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 219 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
242 220
243 // Read all byte sizes up to the sizeof the type. 221 // Read all byte sizes up to the sizeof the type.
244 for (size_t i = 1; i < sizeof(TypeParam); i++) { 222 for (size_t i = 1; i < sizeof(TypeParam); i++) {
245 this->op_memory_.SetMemory( 223 this->op_memory_.SetMemory(
246 0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, static_cast<uint8_t>(i)}); 224 0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, static_cast<uint8_t>(i)});
247 ASSERT_TRUE(this->op_->Eval(0, 5, DWARF_VERSION_MAX)) << "Failed at size " << i; 225 ASSERT_TRUE(this->op_->Eval(0, 5)) << "Failed at size " << i;
248 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed at size " << i; 226 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed at size " << i;
249 ASSERT_EQ(0x94, this->op_->cur_op()) << "Failed at size " << i; 227 ASSERT_EQ(0x94, this->op_->cur_op()) << "Failed at size " << i;
250 TypeParam expected_value = 0; 228 TypeParam expected_value = 0;
@@ -254,17 +232,17 @@ TYPED_TEST_P(DwarfOpTest, op_deref_size) {
254 232
255 // Zero byte read. 233 // Zero byte read.
256 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, 0x00}); 234 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, 0x00});
257 ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX)); 235 ASSERT_FALSE(this->op_->Eval(0, 5));
258 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); 236 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
259 237
260 // Read too many bytes. 238 // Read too many bytes.
261 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, sizeof(TypeParam) + 1}); 239 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, sizeof(TypeParam) + 1});
262 ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX)); 240 ASSERT_FALSE(this->op_->Eval(0, 5));
263 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); 241 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
264 242
265 // Force bad memory read. 243 // Force bad memory read.
266 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x40, 0x94, 0x01}); 244 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x40, 0x94, 0x01});
267 ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX)); 245 ASSERT_FALSE(this->op_->Eval(0, 5));
268 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode()); 246 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
269 EXPECT_EQ(0x4010U, this->op_->LastErrorAddress()); 247 EXPECT_EQ(0x4010U, this->op_->LastErrorAddress());
270} 248}
@@ -284,40 +262,40 @@ TYPED_TEST_P(DwarfOpTest, const_unsigned) {
284 this->op_memory_.SetMemory(0, opcode_buffer); 262 this->op_memory_.SetMemory(0, opcode_buffer);
285 263
286 // const1u 264 // const1u
287 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 265 ASSERT_TRUE(this->op_->Decode());
288 ASSERT_EQ(0x08, this->op_->cur_op()); 266 ASSERT_EQ(0x08, this->op_->cur_op());
289 ASSERT_EQ(1U, this->op_->StackSize()); 267 ASSERT_EQ(1U, this->op_->StackSize());
290 ASSERT_EQ(0x12U, this->op_->StackAt(0)); 268 ASSERT_EQ(0x12U, this->op_->StackAt(0));
291 269
292 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 270 ASSERT_TRUE(this->op_->Decode());
293 ASSERT_EQ(0x08, this->op_->cur_op()); 271 ASSERT_EQ(0x08, this->op_->cur_op());
294 ASSERT_EQ(2U, this->op_->StackSize()); 272 ASSERT_EQ(2U, this->op_->StackSize());
295 ASSERT_EQ(0xffU, this->op_->StackAt(0)); 273 ASSERT_EQ(0xffU, this->op_->StackAt(0));
296 274
297 // const2u 275 // const2u
298 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 276 ASSERT_TRUE(this->op_->Decode());
299 ASSERT_EQ(0x0a, this->op_->cur_op()); 277 ASSERT_EQ(0x0a, this->op_->cur_op());
300 ASSERT_EQ(3U, this->op_->StackSize()); 278 ASSERT_EQ(3U, this->op_->StackSize());
301 ASSERT_EQ(0x1245U, this->op_->StackAt(0)); 279 ASSERT_EQ(0x1245U, this->op_->StackAt(0));
302 280
303 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 281 ASSERT_TRUE(this->op_->Decode());
304 ASSERT_EQ(0x0a, this->op_->cur_op()); 282 ASSERT_EQ(0x0a, this->op_->cur_op());
305 ASSERT_EQ(4U, this->op_->StackSize()); 283 ASSERT_EQ(4U, this->op_->StackSize());
306 ASSERT_EQ(0xff00U, this->op_->StackAt(0)); 284 ASSERT_EQ(0xff00U, this->op_->StackAt(0));
307 285
308 // const4u 286 // const4u
309 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 287 ASSERT_TRUE(this->op_->Decode());
310 ASSERT_EQ(0x0c, this->op_->cur_op()); 288 ASSERT_EQ(0x0c, this->op_->cur_op());
311 ASSERT_EQ(5U, this->op_->StackSize()); 289 ASSERT_EQ(5U, this->op_->StackSize());
312 ASSERT_EQ(0x45342312U, this->op_->StackAt(0)); 290 ASSERT_EQ(0x45342312U, this->op_->StackAt(0));
313 291
314 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 292 ASSERT_TRUE(this->op_->Decode());
315 ASSERT_EQ(0x0c, this->op_->cur_op()); 293 ASSERT_EQ(0x0c, this->op_->cur_op());
316 ASSERT_EQ(6U, this->op_->StackSize()); 294 ASSERT_EQ(6U, this->op_->StackSize());
317 ASSERT_EQ(0xff010203U, this->op_->StackAt(0)); 295 ASSERT_EQ(0xff010203U, this->op_->StackAt(0));
318 296
319 // const8u 297 // const8u
320 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 298 ASSERT_TRUE(this->op_->Decode());
321 ASSERT_EQ(0x0e, this->op_->cur_op()); 299 ASSERT_EQ(0x0e, this->op_->cur_op());
322 ASSERT_EQ(7U, this->op_->StackSize()); 300 ASSERT_EQ(7U, this->op_->StackSize());
323 if (sizeof(TypeParam) == 4) { 301 if (sizeof(TypeParam) == 4) {
@@ -326,7 +304,7 @@ TYPED_TEST_P(DwarfOpTest, const_unsigned) {
326 ASSERT_EQ(0x0102030405060708ULL, this->op_->StackAt(0)); 304 ASSERT_EQ(0x0102030405060708ULL, this->op_->StackAt(0));
327 } 305 }
328 306
329 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 307 ASSERT_TRUE(this->op_->Decode());
330 ASSERT_EQ(0x0e, this->op_->cur_op()); 308 ASSERT_EQ(0x0e, this->op_->cur_op());
331 ASSERT_EQ(8U, this->op_->StackSize()); 309 ASSERT_EQ(8U, this->op_->StackSize());
332 if (sizeof(TypeParam) == 4) { 310 if (sizeof(TypeParam) == 4) {
@@ -351,40 +329,40 @@ TYPED_TEST_P(DwarfOpTest, const_signed) {
351 this->op_memory_.SetMemory(0, opcode_buffer); 329 this->op_memory_.SetMemory(0, opcode_buffer);
352 330
353 // const1s 331 // const1s
354 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 332 ASSERT_TRUE(this->op_->Decode());
355 ASSERT_EQ(0x09, this->op_->cur_op()); 333 ASSERT_EQ(0x09, this->op_->cur_op());
356 ASSERT_EQ(1U, this->op_->StackSize()); 334 ASSERT_EQ(1U, this->op_->StackSize());
357 ASSERT_EQ(0x12U, this->op_->StackAt(0)); 335 ASSERT_EQ(0x12U, this->op_->StackAt(0));
358 336
359 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 337 ASSERT_TRUE(this->op_->Decode());
360 ASSERT_EQ(0x09, this->op_->cur_op()); 338 ASSERT_EQ(0x09, this->op_->cur_op());
361 ASSERT_EQ(2U, this->op_->StackSize()); 339 ASSERT_EQ(2U, this->op_->StackSize());
362 ASSERT_EQ(static_cast<TypeParam>(-1), this->op_->StackAt(0)); 340 ASSERT_EQ(static_cast<TypeParam>(-1), this->op_->StackAt(0));
363 341
364 // const2s 342 // const2s
365 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 343 ASSERT_TRUE(this->op_->Decode());
366 ASSERT_EQ(0x0b, this->op_->cur_op()); 344 ASSERT_EQ(0x0b, this->op_->cur_op());
367 ASSERT_EQ(3U, this->op_->StackSize()); 345 ASSERT_EQ(3U, this->op_->StackSize());
368 ASSERT_EQ(0x3221U, this->op_->StackAt(0)); 346 ASSERT_EQ(0x3221U, this->op_->StackAt(0));
369 347
370 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 348 ASSERT_TRUE(this->op_->Decode());
371 ASSERT_EQ(0x0b, this->op_->cur_op()); 349 ASSERT_EQ(0x0b, this->op_->cur_op());
372 ASSERT_EQ(4U, this->op_->StackSize()); 350 ASSERT_EQ(4U, this->op_->StackSize());
373 ASSERT_EQ(static_cast<TypeParam>(-248), this->op_->StackAt(0)); 351 ASSERT_EQ(static_cast<TypeParam>(-248), this->op_->StackAt(0));
374 352
375 // const4s 353 // const4s
376 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 354 ASSERT_TRUE(this->op_->Decode());
377 ASSERT_EQ(0x0d, this->op_->cur_op()); 355 ASSERT_EQ(0x0d, this->op_->cur_op());
378 ASSERT_EQ(5U, this->op_->StackSize()); 356 ASSERT_EQ(5U, this->op_->StackSize());
379 ASSERT_EQ(0x12233445U, this->op_->StackAt(0)); 357 ASSERT_EQ(0x12233445U, this->op_->StackAt(0));
380 358
381 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 359 ASSERT_TRUE(this->op_->Decode());
382 ASSERT_EQ(0x0d, this->op_->cur_op()); 360 ASSERT_EQ(0x0d, this->op_->cur_op());
383 ASSERT_EQ(6U, this->op_->StackSize()); 361 ASSERT_EQ(6U, this->op_->StackSize());
384 ASSERT_EQ(static_cast<TypeParam>(-16580095), this->op_->StackAt(0)); 362 ASSERT_EQ(static_cast<TypeParam>(-16580095), this->op_->StackAt(0));
385 363
386 // const8s 364 // const8s
387 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 365 ASSERT_TRUE(this->op_->Decode());
388 ASSERT_EQ(0x0f, this->op_->cur_op()); 366 ASSERT_EQ(0x0f, this->op_->cur_op());
389 ASSERT_EQ(7U, this->op_->StackSize()); 367 ASSERT_EQ(7U, this->op_->StackSize());
390 if (sizeof(TypeParam) == 4) { 368 if (sizeof(TypeParam) == 4) {
@@ -393,7 +371,7 @@ TYPED_TEST_P(DwarfOpTest, const_signed) {
393 ASSERT_EQ(0x1223344556677889ULL, this->op_->StackAt(0)); 371 ASSERT_EQ(0x1223344556677889ULL, this->op_->StackAt(0));
394 } 372 }
395 373
396 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 374 ASSERT_TRUE(this->op_->Decode());
397 ASSERT_EQ(0x0f, this->op_->cur_op()); 375 ASSERT_EQ(0x0f, this->op_->cur_op());
398 ASSERT_EQ(8U, this->op_->StackSize()); 376 ASSERT_EQ(8U, this->op_->StackSize());
399 if (sizeof(TypeParam) == 4) { 377 if (sizeof(TypeParam) == 4) {
@@ -414,28 +392,28 @@ TYPED_TEST_P(DwarfOpTest, const_uleb) {
414 this->op_memory_.SetMemory(0, opcode_buffer); 392 this->op_memory_.SetMemory(0, opcode_buffer);
415 393
416 // Single byte ULEB128 394 // Single byte ULEB128
417 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 395 ASSERT_TRUE(this->op_->Decode());
418 ASSERT_EQ(0x10, this->op_->cur_op()); 396 ASSERT_EQ(0x10, this->op_->cur_op());
419 ASSERT_EQ(1U, this->op_->StackSize()); 397 ASSERT_EQ(1U, this->op_->StackSize());
420 ASSERT_EQ(0x22U, this->op_->StackAt(0)); 398 ASSERT_EQ(0x22U, this->op_->StackAt(0));
421 399
422 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 400 ASSERT_TRUE(this->op_->Decode());
423 ASSERT_EQ(0x10, this->op_->cur_op()); 401 ASSERT_EQ(0x10, this->op_->cur_op());
424 ASSERT_EQ(2U, this->op_->StackSize()); 402 ASSERT_EQ(2U, this->op_->StackSize());
425 ASSERT_EQ(0x7fU, this->op_->StackAt(0)); 403 ASSERT_EQ(0x7fU, this->op_->StackAt(0));
426 404
427 // Multi byte ULEB128 405 // Multi byte ULEB128
428 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 406 ASSERT_TRUE(this->op_->Decode());
429 ASSERT_EQ(0x10, this->op_->cur_op()); 407 ASSERT_EQ(0x10, this->op_->cur_op());
430 ASSERT_EQ(3U, this->op_->StackSize()); 408 ASSERT_EQ(3U, this->op_->StackSize());
431 ASSERT_EQ(0x1122U, this->op_->StackAt(0)); 409 ASSERT_EQ(0x1122U, this->op_->StackAt(0));
432 410
433 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 411 ASSERT_TRUE(this->op_->Decode());
434 ASSERT_EQ(0x10, this->op_->cur_op()); 412 ASSERT_EQ(0x10, this->op_->cur_op());
435 ASSERT_EQ(4U, this->op_->StackSize()); 413 ASSERT_EQ(4U, this->op_->StackSize());
436 ASSERT_EQ(0x3a22U, this->op_->StackAt(0)); 414 ASSERT_EQ(0x3a22U, this->op_->StackAt(0));
437 415
438 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 416 ASSERT_TRUE(this->op_->Decode());
439 ASSERT_EQ(0x10, this->op_->cur_op()); 417 ASSERT_EQ(0x10, this->op_->cur_op());
440 ASSERT_EQ(5U, this->op_->StackSize()); 418 ASSERT_EQ(5U, this->op_->StackSize());
441 if (sizeof(TypeParam) == 4) { 419 if (sizeof(TypeParam) == 4) {
@@ -444,7 +422,7 @@ TYPED_TEST_P(DwarfOpTest, const_uleb) {
444 ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0)); 422 ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0));
445 } 423 }
446 424
447 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 425 ASSERT_TRUE(this->op_->Decode());
448 ASSERT_EQ(0x10, this->op_->cur_op()); 426 ASSERT_EQ(0x10, this->op_->cur_op());
449 ASSERT_EQ(6U, this->op_->StackSize()); 427 ASSERT_EQ(6U, this->op_->StackSize());
450 if (sizeof(TypeParam) == 4) { 428 if (sizeof(TypeParam) == 4) {
@@ -480,28 +458,28 @@ TYPED_TEST_P(DwarfOpTest, const_sleb) {
480 this->op_memory_.SetMemory(0, opcode_buffer); 458 this->op_memory_.SetMemory(0, opcode_buffer);
481 459
482 // Single byte SLEB128 460 // Single byte SLEB128
483 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 461 ASSERT_TRUE(this->op_->Decode());
484 ASSERT_EQ(0x11, this->op_->cur_op()); 462 ASSERT_EQ(0x11, this->op_->cur_op());
485 ASSERT_EQ(1U, this->op_->StackSize()); 463 ASSERT_EQ(1U, this->op_->StackSize());
486 ASSERT_EQ(0x22U, this->op_->StackAt(0)); 464 ASSERT_EQ(0x22U, this->op_->StackAt(0));
487 465
488 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 466 ASSERT_TRUE(this->op_->Decode());
489 ASSERT_EQ(0x11, this->op_->cur_op()); 467 ASSERT_EQ(0x11, this->op_->cur_op());
490 ASSERT_EQ(2U, this->op_->StackSize()); 468 ASSERT_EQ(2U, this->op_->StackSize());
491 ASSERT_EQ(static_cast<TypeParam>(-1), this->op_->StackAt(0)); 469 ASSERT_EQ(static_cast<TypeParam>(-1), this->op_->StackAt(0));
492 470
493 // Multi byte SLEB128 471 // Multi byte SLEB128
494 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 472 ASSERT_TRUE(this->op_->Decode());
495 ASSERT_EQ(0x11, this->op_->cur_op()); 473 ASSERT_EQ(0x11, this->op_->cur_op());
496 ASSERT_EQ(3U, this->op_->StackSize()); 474 ASSERT_EQ(3U, this->op_->StackSize());
497 ASSERT_EQ(0x1122U, this->op_->StackAt(0)); 475 ASSERT_EQ(0x1122U, this->op_->StackAt(0));
498 476
499 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 477 ASSERT_TRUE(this->op_->Decode());
500 ASSERT_EQ(0x11, this->op_->cur_op()); 478 ASSERT_EQ(0x11, this->op_->cur_op());
501 ASSERT_EQ(4U, this->op_->StackSize()); 479 ASSERT_EQ(4U, this->op_->StackSize());
502 ASSERT_EQ(static_cast<TypeParam>(-1502), this->op_->StackAt(0)); 480 ASSERT_EQ(static_cast<TypeParam>(-1502), this->op_->StackAt(0));
503 481
504 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 482 ASSERT_TRUE(this->op_->Decode());
505 ASSERT_EQ(0x11, this->op_->cur_op()); 483 ASSERT_EQ(0x11, this->op_->cur_op());
506 ASSERT_EQ(5U, this->op_->StackSize()); 484 ASSERT_EQ(5U, this->op_->StackSize());
507 if (sizeof(TypeParam) == 4) { 485 if (sizeof(TypeParam) == 4) {
@@ -510,7 +488,7 @@ TYPED_TEST_P(DwarfOpTest, const_sleb) {
510 ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0)); 488 ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0));
511 } 489 }
512 490
513 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 491 ASSERT_TRUE(this->op_->Decode());
514 ASSERT_EQ(0x11, this->op_->cur_op()); 492 ASSERT_EQ(0x11, this->op_->cur_op());
515 ASSERT_EQ(6U, this->op_->StackSize()); 493 ASSERT_EQ(6U, this->op_->StackSize());
516 if (sizeof(TypeParam) == 4) { 494 if (sizeof(TypeParam) == 4) {
@@ -531,21 +509,21 @@ TYPED_TEST_P(DwarfOpTest, op_dup) {
531 }; 509 };
532 this->op_memory_.SetMemory(0, opcode_buffer); 510 this->op_memory_.SetMemory(0, opcode_buffer);
533 511
534 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 512 ASSERT_FALSE(this->op_->Decode());
535 ASSERT_EQ(0x12, this->op_->cur_op()); 513 ASSERT_EQ(0x12, this->op_->cur_op());
536 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 514 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
537 515
538 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 516 ASSERT_TRUE(this->op_->Decode());
539 ASSERT_EQ(1U, this->op_->StackSize()); 517 ASSERT_EQ(1U, this->op_->StackSize());
540 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 518 ASSERT_TRUE(this->op_->Decode());
541 ASSERT_EQ(0x12, this->op_->cur_op()); 519 ASSERT_EQ(0x12, this->op_->cur_op());
542 ASSERT_EQ(2U, this->op_->StackSize()); 520 ASSERT_EQ(2U, this->op_->StackSize());
543 ASSERT_EQ(0x15U, this->op_->StackAt(0)); 521 ASSERT_EQ(0x15U, this->op_->StackAt(0));
544 ASSERT_EQ(0x15U, this->op_->StackAt(1)); 522 ASSERT_EQ(0x15U, this->op_->StackAt(1));
545 523
546 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 524 ASSERT_TRUE(this->op_->Decode());
547 ASSERT_EQ(3U, this->op_->StackSize()); 525 ASSERT_EQ(3U, this->op_->StackSize());
548 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 526 ASSERT_TRUE(this->op_->Decode());
549 ASSERT_EQ(0x12, this->op_->cur_op()); 527 ASSERT_EQ(0x12, this->op_->cur_op());
550 ASSERT_EQ(4U, this->op_->StackSize()); 528 ASSERT_EQ(4U, this->op_->StackSize());
551 ASSERT_EQ(0x23U, this->op_->StackAt(0)); 529 ASSERT_EQ(0x23U, this->op_->StackAt(0));
@@ -565,21 +543,21 @@ TYPED_TEST_P(DwarfOpTest, op_drop) {
565 }; 543 };
566 this->op_memory_.SetMemory(0, opcode_buffer); 544 this->op_memory_.SetMemory(0, opcode_buffer);
567 545
568 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 546 ASSERT_TRUE(this->op_->Decode());
569 ASSERT_EQ(1U, this->op_->StackSize()); 547 ASSERT_EQ(1U, this->op_->StackSize());
570 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 548 ASSERT_TRUE(this->op_->Decode());
571 ASSERT_EQ(2U, this->op_->StackSize()); 549 ASSERT_EQ(2U, this->op_->StackSize());
572 550
573 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 551 ASSERT_TRUE(this->op_->Decode());
574 ASSERT_EQ(0x13, this->op_->cur_op()); 552 ASSERT_EQ(0x13, this->op_->cur_op());
575 ASSERT_EQ(1U, this->op_->StackSize()); 553 ASSERT_EQ(1U, this->op_->StackSize());
576 ASSERT_EQ(0x10U, this->op_->StackAt(0)); 554 ASSERT_EQ(0x10U, this->op_->StackAt(0));
577 555
578 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 556 ASSERT_TRUE(this->op_->Decode());
579 ASSERT_EQ(0x13, this->op_->cur_op()); 557 ASSERT_EQ(0x13, this->op_->cur_op());
580 ASSERT_EQ(0U, this->op_->StackSize()); 558 ASSERT_EQ(0U, this->op_->StackSize());
581 559
582 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 560 ASSERT_FALSE(this->op_->Decode());
583 ASSERT_EQ(0x13, this->op_->cur_op()); 561 ASSERT_EQ(0x13, this->op_->cur_op());
584 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 562 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
585} 563}
@@ -597,24 +575,24 @@ TYPED_TEST_P(DwarfOpTest, op_over) {
597 }; 575 };
598 this->op_memory_.SetMemory(0, opcode_buffer); 576 this->op_memory_.SetMemory(0, opcode_buffer);
599 577
600 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 578 ASSERT_TRUE(this->op_->Decode());
601 ASSERT_EQ(1U, this->op_->StackSize()); 579 ASSERT_EQ(1U, this->op_->StackSize());
602 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 580 ASSERT_TRUE(this->op_->Decode());
603 ASSERT_EQ(2U, this->op_->StackSize()); 581 ASSERT_EQ(2U, this->op_->StackSize());
604 582
605 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 583 ASSERT_TRUE(this->op_->Decode());
606 ASSERT_EQ(0x14, this->op_->cur_op()); 584 ASSERT_EQ(0x14, this->op_->cur_op());
607 ASSERT_EQ(3U, this->op_->StackSize()); 585 ASSERT_EQ(3U, this->op_->StackSize());
608 ASSERT_EQ(0x1aU, this->op_->StackAt(0)); 586 ASSERT_EQ(0x1aU, this->op_->StackAt(0));
609 ASSERT_EQ(0xedU, this->op_->StackAt(1)); 587 ASSERT_EQ(0xedU, this->op_->StackAt(1));
610 ASSERT_EQ(0x1aU, this->op_->StackAt(2)); 588 ASSERT_EQ(0x1aU, this->op_->StackAt(2));
611 589
612 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 590 ASSERT_TRUE(this->op_->Decode());
613 ASSERT_EQ(2U, this->op_->StackSize()); 591 ASSERT_EQ(2U, this->op_->StackSize());
614 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 592 ASSERT_TRUE(this->op_->Decode());
615 ASSERT_EQ(1U, this->op_->StackSize()); 593 ASSERT_EQ(1U, this->op_->StackSize());
616 594
617 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 595 ASSERT_FALSE(this->op_->Decode());
618 ASSERT_EQ(0x14, this->op_->cur_op()); 596 ASSERT_EQ(0x14, this->op_->cur_op());
619 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 597 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
620} 598}
@@ -632,14 +610,14 @@ TYPED_TEST_P(DwarfOpTest, op_pick) {
632 }; 610 };
633 this->op_memory_.SetMemory(0, opcode_buffer); 611 this->op_memory_.SetMemory(0, opcode_buffer);
634 612
635 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 613 ASSERT_TRUE(this->op_->Decode());
636 ASSERT_EQ(1U, this->op_->StackSize()); 614 ASSERT_EQ(1U, this->op_->StackSize());
637 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 615 ASSERT_TRUE(this->op_->Decode());
638 ASSERT_EQ(2U, this->op_->StackSize()); 616 ASSERT_EQ(2U, this->op_->StackSize());
639 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 617 ASSERT_TRUE(this->op_->Decode());
640 ASSERT_EQ(3U, this->op_->StackSize()); 618 ASSERT_EQ(3U, this->op_->StackSize());
641 619
642 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 620 ASSERT_TRUE(this->op_->Decode());
643 ASSERT_EQ(0x15, this->op_->cur_op()); 621 ASSERT_EQ(0x15, this->op_->cur_op());
644 ASSERT_EQ(4U, this->op_->StackSize()); 622 ASSERT_EQ(4U, this->op_->StackSize());
645 ASSERT_EQ(0xedU, this->op_->StackAt(0)); 623 ASSERT_EQ(0xedU, this->op_->StackAt(0));
@@ -647,7 +625,7 @@ TYPED_TEST_P(DwarfOpTest, op_pick) {
647 ASSERT_EQ(0xedU, this->op_->StackAt(2)); 625 ASSERT_EQ(0xedU, this->op_->StackAt(2));
648 ASSERT_EQ(0x1aU, this->op_->StackAt(3)); 626 ASSERT_EQ(0x1aU, this->op_->StackAt(3));
649 627
650 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 628 ASSERT_TRUE(this->op_->Decode());
651 ASSERT_EQ(0x15, this->op_->cur_op()); 629 ASSERT_EQ(0x15, this->op_->cur_op());
652 ASSERT_EQ(5U, this->op_->StackSize()); 630 ASSERT_EQ(5U, this->op_->StackSize());
653 ASSERT_EQ(0x1aU, this->op_->StackAt(0)); 631 ASSERT_EQ(0x1aU, this->op_->StackAt(0));
@@ -656,7 +634,7 @@ TYPED_TEST_P(DwarfOpTest, op_pick) {
656 ASSERT_EQ(0xedU, this->op_->StackAt(3)); 634 ASSERT_EQ(0xedU, this->op_->StackAt(3));
657 ASSERT_EQ(0x1aU, this->op_->StackAt(4)); 635 ASSERT_EQ(0x1aU, this->op_->StackAt(4));
658 636
659 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 637 ASSERT_FALSE(this->op_->Decode());
660 ASSERT_EQ(0x15, this->op_->cur_op()); 638 ASSERT_EQ(0x15, this->op_->cur_op());
661 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 639 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
662} 640}
@@ -672,23 +650,23 @@ TYPED_TEST_P(DwarfOpTest, op_swap) {
672 }; 650 };
673 this->op_memory_.SetMemory(0, opcode_buffer); 651 this->op_memory_.SetMemory(0, opcode_buffer);
674 652
675 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 653 ASSERT_TRUE(this->op_->Decode());
676 ASSERT_EQ(1U, this->op_->StackSize()); 654 ASSERT_EQ(1U, this->op_->StackSize());
677 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 655 ASSERT_TRUE(this->op_->Decode());
678 ASSERT_EQ(2U, this->op_->StackSize()); 656 ASSERT_EQ(2U, this->op_->StackSize());
679 ASSERT_EQ(0xabU, this->op_->StackAt(0)); 657 ASSERT_EQ(0xabU, this->op_->StackAt(0));
680 ASSERT_EQ(0x26U, this->op_->StackAt(1)); 658 ASSERT_EQ(0x26U, this->op_->StackAt(1));
681 659
682 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 660 ASSERT_TRUE(this->op_->Decode());
683 ASSERT_EQ(0x16, this->op_->cur_op()); 661 ASSERT_EQ(0x16, this->op_->cur_op());
684 ASSERT_EQ(2U, this->op_->StackSize()); 662 ASSERT_EQ(2U, this->op_->StackSize());
685 ASSERT_EQ(0x26U, this->op_->StackAt(0)); 663 ASSERT_EQ(0x26U, this->op_->StackAt(0));
686 ASSERT_EQ(0xabU, this->op_->StackAt(1)); 664 ASSERT_EQ(0xabU, this->op_->StackAt(1));
687 665
688 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 666 ASSERT_TRUE(this->op_->Decode());
689 ASSERT_EQ(1U, this->op_->StackSize()); 667 ASSERT_EQ(1U, this->op_->StackSize());
690 668
691 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 669 ASSERT_FALSE(this->op_->Decode());
692 ASSERT_EQ(0x16, this->op_->cur_op()); 670 ASSERT_EQ(0x16, this->op_->cur_op());
693 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 671 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
694} 672}
@@ -706,28 +684,28 @@ TYPED_TEST_P(DwarfOpTest, op_rot) {
706 }; 684 };
707 this->op_memory_.SetMemory(0, opcode_buffer); 685 this->op_memory_.SetMemory(0, opcode_buffer);
708 686
709 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 687 ASSERT_FALSE(this->op_->Decode());
710 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 688 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
711 689
712 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 690 ASSERT_TRUE(this->op_->Decode());
713 ASSERT_EQ(1U, this->op_->StackSize()); 691 ASSERT_EQ(1U, this->op_->StackSize());
714 692
715 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 693 ASSERT_FALSE(this->op_->Decode());
716 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 694 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
717 695
718 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 696 ASSERT_TRUE(this->op_->Decode());
719 ASSERT_EQ(2U, this->op_->StackSize()); 697 ASSERT_EQ(2U, this->op_->StackSize());
720 698
721 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 699 ASSERT_FALSE(this->op_->Decode());
722 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 700 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
723 701
724 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 702 ASSERT_TRUE(this->op_->Decode());
725 ASSERT_EQ(3U, this->op_->StackSize()); 703 ASSERT_EQ(3U, this->op_->StackSize());
726 ASSERT_EQ(0x30U, this->op_->StackAt(0)); 704 ASSERT_EQ(0x30U, this->op_->StackAt(0));
727 ASSERT_EQ(0x20U, this->op_->StackAt(1)); 705 ASSERT_EQ(0x20U, this->op_->StackAt(1));
728 ASSERT_EQ(0x10U, this->op_->StackAt(2)); 706 ASSERT_EQ(0x10U, this->op_->StackAt(2));
729 707
730 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 708 ASSERT_TRUE(this->op_->Decode());
731 ASSERT_EQ(0x17, this->op_->cur_op()); 709 ASSERT_EQ(0x17, this->op_->cur_op());
732 ASSERT_EQ(3U, this->op_->StackSize()); 710 ASSERT_EQ(3U, this->op_->StackSize());
733 ASSERT_EQ(0x20U, this->op_->StackAt(0)); 711 ASSERT_EQ(0x20U, this->op_->StackAt(0));
@@ -756,30 +734,30 @@ TYPED_TEST_P(DwarfOpTest, op_abs) {
756 opcode_buffer.push_back(0x19); 734 opcode_buffer.push_back(0x19);
757 this->op_memory_.SetMemory(0, opcode_buffer); 735 this->op_memory_.SetMemory(0, opcode_buffer);
758 736
759 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 737 ASSERT_FALSE(this->op_->Decode());
760 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 738 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
761 739
762 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 740 ASSERT_TRUE(this->op_->Decode());
763 ASSERT_EQ(1U, this->op_->StackSize()); 741 ASSERT_EQ(1U, this->op_->StackSize());
764 ASSERT_EQ(0x10U, this->op_->StackAt(0)); 742 ASSERT_EQ(0x10U, this->op_->StackAt(0));
765 743
766 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 744 ASSERT_TRUE(this->op_->Decode());
767 ASSERT_EQ(0x19, this->op_->cur_op()); 745 ASSERT_EQ(0x19, this->op_->cur_op());
768 ASSERT_EQ(1U, this->op_->StackSize()); 746 ASSERT_EQ(1U, this->op_->StackSize());
769 ASSERT_EQ(0x10U, this->op_->StackAt(0)); 747 ASSERT_EQ(0x10U, this->op_->StackAt(0));
770 748
771 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 749 ASSERT_TRUE(this->op_->Decode());
772 ASSERT_EQ(2U, this->op_->StackSize()); 750 ASSERT_EQ(2U, this->op_->StackSize());
773 751
774 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 752 ASSERT_TRUE(this->op_->Decode());
775 ASSERT_EQ(0x19, this->op_->cur_op()); 753 ASSERT_EQ(0x19, this->op_->cur_op());
776 ASSERT_EQ(2U, this->op_->StackSize()); 754 ASSERT_EQ(2U, this->op_->StackSize());
777 ASSERT_EQ(0x1U, this->op_->StackAt(0)); 755 ASSERT_EQ(0x1U, this->op_->StackAt(0));
778 756
779 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 757 ASSERT_TRUE(this->op_->Decode());
780 ASSERT_EQ(3U, this->op_->StackSize()); 758 ASSERT_EQ(3U, this->op_->StackSize());
781 759
782 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 760 ASSERT_TRUE(this->op_->Decode());
783 ASSERT_EQ(0x19, this->op_->cur_op()); 761 ASSERT_EQ(0x19, this->op_->cur_op());
784 ASSERT_EQ(3U, this->op_->StackSize()); 762 ASSERT_EQ(3U, this->op_->StackSize());
785 if (sizeof(TypeParam) == 4) { 763 if (sizeof(TypeParam) == 4) {
@@ -808,56 +786,56 @@ TYPED_TEST_P(DwarfOpTest, op_and) {
808 }; 786 };
809 this->op_memory_.SetMemory(0, opcode_buffer); 787 this->op_memory_.SetMemory(0, opcode_buffer);
810 788
811 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 789 ASSERT_FALSE(this->op_->Decode());
812 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 790 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
813 791
814 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 792 ASSERT_TRUE(this->op_->Decode());
815 ASSERT_EQ(1U, this->op_->StackSize()); 793 ASSERT_EQ(1U, this->op_->StackSize());
816 794
817 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 795 ASSERT_FALSE(this->op_->Decode());
818 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 796 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
819 797
820 // Two positive values. 798 // Two positive values.
821 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 799 ASSERT_TRUE(this->op_->Decode());
822 ASSERT_EQ(2U, this->op_->StackSize()); 800 ASSERT_EQ(2U, this->op_->StackSize());
823 801
824 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 802 ASSERT_TRUE(this->op_->Decode());
825 ASSERT_EQ(0x1b, this->op_->cur_op()); 803 ASSERT_EQ(0x1b, this->op_->cur_op());
826 ASSERT_EQ(1U, this->op_->StackSize()); 804 ASSERT_EQ(1U, this->op_->StackSize());
827 ASSERT_EQ(0x10U, this->op_->StackAt(0)); 805 ASSERT_EQ(0x10U, this->op_->StackAt(0));
828 806
829 // Two negative values. 807 // Two negative values.
830 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 808 ASSERT_TRUE(this->op_->Decode());
831 ASSERT_EQ(2U, this->op_->StackSize()); 809 ASSERT_EQ(2U, this->op_->StackSize());
832 810
833 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 811 ASSERT_TRUE(this->op_->Decode());
834 ASSERT_EQ(3U, this->op_->StackSize()); 812 ASSERT_EQ(3U, this->op_->StackSize());
835 813
836 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 814 ASSERT_TRUE(this->op_->Decode());
837 ASSERT_EQ(0x1b, this->op_->cur_op()); 815 ASSERT_EQ(0x1b, this->op_->cur_op());
838 ASSERT_EQ(2U, this->op_->StackSize()); 816 ASSERT_EQ(2U, this->op_->StackSize());
839 ASSERT_EQ(0x04U, this->op_->StackAt(0)); 817 ASSERT_EQ(0x04U, this->op_->StackAt(0));
840 818
841 // One negative value, one positive value. 819 // One negative value, one positive value.
842 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 820 ASSERT_TRUE(this->op_->Decode());
843 ASSERT_EQ(3U, this->op_->StackSize()); 821 ASSERT_EQ(3U, this->op_->StackSize());
844 822
845 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 823 ASSERT_TRUE(this->op_->Decode());
846 ASSERT_EQ(4U, this->op_->StackSize()); 824 ASSERT_EQ(4U, this->op_->StackSize());
847 825
848 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 826 ASSERT_TRUE(this->op_->Decode());
849 ASSERT_EQ(0x1b, this->op_->cur_op()); 827 ASSERT_EQ(0x1b, this->op_->cur_op());
850 ASSERT_EQ(3U, this->op_->StackSize()); 828 ASSERT_EQ(3U, this->op_->StackSize());
851 ASSERT_EQ(static_cast<TypeParam>(-4), this->op_->StackAt(0)); 829 ASSERT_EQ(static_cast<TypeParam>(-4), this->op_->StackAt(0));
852 830
853 // Divide by zero. 831 // Divide by zero.
854 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 832 ASSERT_TRUE(this->op_->Decode());
855 ASSERT_EQ(4U, this->op_->StackSize()); 833 ASSERT_EQ(4U, this->op_->StackSize());
856 834
857 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 835 ASSERT_TRUE(this->op_->Decode());
858 ASSERT_EQ(5U, this->op_->StackSize()); 836 ASSERT_EQ(5U, this->op_->StackSize());
859 837
860 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 838 ASSERT_FALSE(this->op_->Decode());
861 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); 839 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
862} 840}
863 841
@@ -874,19 +852,19 @@ TYPED_TEST_P(DwarfOpTest, op_div) {
874 }; 852 };
875 this->op_memory_.SetMemory(0, opcode_buffer); 853 this->op_memory_.SetMemory(0, opcode_buffer);
876 854
877 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 855 ASSERT_FALSE(this->op_->Decode());
878 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 856 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
879 857
880 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 858 ASSERT_TRUE(this->op_->Decode());
881 ASSERT_EQ(1U, this->op_->StackSize()); 859 ASSERT_EQ(1U, this->op_->StackSize());
882 860
883 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 861 ASSERT_FALSE(this->op_->Decode());
884 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 862 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
885 863
886 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 864 ASSERT_TRUE(this->op_->Decode());
887 ASSERT_EQ(2U, this->op_->StackSize()); 865 ASSERT_EQ(2U, this->op_->StackSize());
888 866
889 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 867 ASSERT_TRUE(this->op_->Decode());
890 ASSERT_EQ(0x1a, this->op_->cur_op()); 868 ASSERT_EQ(0x1a, this->op_->cur_op());
891 ASSERT_EQ(1U, this->op_->StackSize()); 869 ASSERT_EQ(1U, this->op_->StackSize());
892 ASSERT_EQ(0x40U, this->op_->StackAt(0)); 870 ASSERT_EQ(0x40U, this->op_->StackAt(0));
@@ -905,19 +883,19 @@ TYPED_TEST_P(DwarfOpTest, op_minus) {
905 }; 883 };
906 this->op_memory_.SetMemory(0, opcode_buffer); 884 this->op_memory_.SetMemory(0, opcode_buffer);
907 885
908 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 886 ASSERT_FALSE(this->op_->Decode());
909 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 887 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
910 888
911 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 889 ASSERT_TRUE(this->op_->Decode());
912 ASSERT_EQ(1U, this->op_->StackSize()); 890 ASSERT_EQ(1U, this->op_->StackSize());
913 891
914 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 892 ASSERT_FALSE(this->op_->Decode());
915 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 893 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
916 894
917 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 895 ASSERT_TRUE(this->op_->Decode());
918 ASSERT_EQ(2U, this->op_->StackSize()); 896 ASSERT_EQ(2U, this->op_->StackSize());
919 897
920 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 898 ASSERT_TRUE(this->op_->Decode());
921 ASSERT_EQ(0x1c, this->op_->cur_op()); 899 ASSERT_EQ(0x1c, this->op_->cur_op());
922 ASSERT_EQ(1U, this->op_->StackSize()); 900 ASSERT_EQ(1U, this->op_->StackSize());
923 ASSERT_EQ(0x44U, this->op_->StackAt(0)); 901 ASSERT_EQ(0x44U, this->op_->StackAt(0));
@@ -938,29 +916,29 @@ TYPED_TEST_P(DwarfOpTest, op_mod) {
938 }; 916 };
939 this->op_memory_.SetMemory(0, opcode_buffer); 917 this->op_memory_.SetMemory(0, opcode_buffer);
940 918
941 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 919 ASSERT_FALSE(this->op_->Decode());
942 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 920 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
943 921
944 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 922 ASSERT_TRUE(this->op_->Decode());
945 ASSERT_EQ(1U, this->op_->StackSize()); 923 ASSERT_EQ(1U, this->op_->StackSize());
946 924
947 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 925 ASSERT_FALSE(this->op_->Decode());
948 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 926 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
949 927
950 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 928 ASSERT_TRUE(this->op_->Decode());
951 ASSERT_EQ(2U, this->op_->StackSize()); 929 ASSERT_EQ(2U, this->op_->StackSize());
952 930
953 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 931 ASSERT_TRUE(this->op_->Decode());
954 ASSERT_EQ(0x1d, this->op_->cur_op()); 932 ASSERT_EQ(0x1d, this->op_->cur_op());
955 ASSERT_EQ(1U, this->op_->StackSize()); 933 ASSERT_EQ(1U, this->op_->StackSize());
956 ASSERT_EQ(0x03U, this->op_->StackAt(0)); 934 ASSERT_EQ(0x03U, this->op_->StackAt(0));
957 935
958 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 936 ASSERT_TRUE(this->op_->Decode());
959 ASSERT_EQ(2U, this->op_->StackSize()); 937 ASSERT_EQ(2U, this->op_->StackSize());
960 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 938 ASSERT_TRUE(this->op_->Decode());
961 ASSERT_EQ(3U, this->op_->StackSize()); 939 ASSERT_EQ(3U, this->op_->StackSize());
962 940
963 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 941 ASSERT_FALSE(this->op_->Decode());
964 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); 942 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
965} 943}
966 944
@@ -977,19 +955,19 @@ TYPED_TEST_P(DwarfOpTest, op_mul) {
977 }; 955 };
978 this->op_memory_.SetMemory(0, opcode_buffer); 956 this->op_memory_.SetMemory(0, opcode_buffer);
979 957
980 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 958 ASSERT_FALSE(this->op_->Decode());
981 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 959 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
982 960
983 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 961 ASSERT_TRUE(this->op_->Decode());
984 ASSERT_EQ(1U, this->op_->StackSize()); 962 ASSERT_EQ(1U, this->op_->StackSize());
985 963
986 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 964 ASSERT_FALSE(this->op_->Decode());
987 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 965 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
988 966
989 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 967 ASSERT_TRUE(this->op_->Decode());
990 ASSERT_EQ(2U, this->op_->StackSize()); 968 ASSERT_EQ(2U, this->op_->StackSize());
991 969
992 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 970 ASSERT_TRUE(this->op_->Decode());
993 ASSERT_EQ(0x1e, this->op_->cur_op()); 971 ASSERT_EQ(0x1e, this->op_->cur_op());
994 ASSERT_EQ(1U, this->op_->StackSize()); 972 ASSERT_EQ(1U, this->op_->StackSize());
995 ASSERT_EQ(0x120U, this->op_->StackAt(0)); 973 ASSERT_EQ(0x120U, this->op_->StackAt(0));
@@ -1006,21 +984,21 @@ TYPED_TEST_P(DwarfOpTest, op_neg) {
1006 }; 984 };
1007 this->op_memory_.SetMemory(0, opcode_buffer); 985 this->op_memory_.SetMemory(0, opcode_buffer);
1008 986
1009 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 987 ASSERT_FALSE(this->op_->Decode());
1010 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 988 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1011 989
1012 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 990 ASSERT_TRUE(this->op_->Decode());
1013 ASSERT_EQ(1U, this->op_->StackSize()); 991 ASSERT_EQ(1U, this->op_->StackSize());
1014 992
1015 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 993 ASSERT_TRUE(this->op_->Decode());
1016 ASSERT_EQ(0x1f, this->op_->cur_op()); 994 ASSERT_EQ(0x1f, this->op_->cur_op());
1017 ASSERT_EQ(1U, this->op_->StackSize()); 995 ASSERT_EQ(1U, this->op_->StackSize());
1018 ASSERT_EQ(static_cast<TypeParam>(-72), this->op_->StackAt(0)); 996 ASSERT_EQ(static_cast<TypeParam>(-72), this->op_->StackAt(0));
1019 997
1020 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 998 ASSERT_TRUE(this->op_->Decode());
1021 ASSERT_EQ(2U, this->op_->StackSize()); 999 ASSERT_EQ(2U, this->op_->StackSize());
1022 1000
1023 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1001 ASSERT_TRUE(this->op_->Decode());
1024 ASSERT_EQ(0x1f, this->op_->cur_op()); 1002 ASSERT_EQ(0x1f, this->op_->cur_op());
1025 ASSERT_EQ(2U, this->op_->StackSize()); 1003 ASSERT_EQ(2U, this->op_->StackSize());
1026 ASSERT_EQ(0x01U, this->op_->StackAt(0)); 1004 ASSERT_EQ(0x01U, this->op_->StackAt(0));
@@ -1037,21 +1015,21 @@ TYPED_TEST_P(DwarfOpTest, op_not) {
1037 }; 1015 };
1038 this->op_memory_.SetMemory(0, opcode_buffer); 1016 this->op_memory_.SetMemory(0, opcode_buffer);
1039 1017
1040 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1018 ASSERT_FALSE(this->op_->Decode());
1041 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1019 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1042 1020
1043 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1021 ASSERT_TRUE(this->op_->Decode());
1044 ASSERT_EQ(1U, this->op_->StackSize()); 1022 ASSERT_EQ(1U, this->op_->StackSize());
1045 1023
1046 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1024 ASSERT_TRUE(this->op_->Decode());
1047 ASSERT_EQ(0x20, this->op_->cur_op()); 1025 ASSERT_EQ(0x20, this->op_->cur_op());
1048 ASSERT_EQ(1U, this->op_->StackSize()); 1026 ASSERT_EQ(1U, this->op_->StackSize());
1049 ASSERT_EQ(static_cast<TypeParam>(-5), this->op_->StackAt(0)); 1027 ASSERT_EQ(static_cast<TypeParam>(-5), this->op_->StackAt(0));
1050 1028
1051 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1029 ASSERT_TRUE(this->op_->Decode());
1052 ASSERT_EQ(2U, this->op_->StackSize()); 1030 ASSERT_EQ(2U, this->op_->StackSize());
1053 1031
1054 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1032 ASSERT_TRUE(this->op_->Decode());
1055 ASSERT_EQ(0x20, this->op_->cur_op()); 1033 ASSERT_EQ(0x20, this->op_->cur_op());
1056 ASSERT_EQ(2U, this->op_->StackSize()); 1034 ASSERT_EQ(2U, this->op_->StackSize());
1057 ASSERT_EQ(0x03U, this->op_->StackAt(0)); 1035 ASSERT_EQ(0x03U, this->op_->StackAt(0));
@@ -1070,19 +1048,19 @@ TYPED_TEST_P(DwarfOpTest, op_or) {
1070 }; 1048 };
1071 this->op_memory_.SetMemory(0, opcode_buffer); 1049 this->op_memory_.SetMemory(0, opcode_buffer);
1072 1050
1073 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1051 ASSERT_FALSE(this->op_->Decode());
1074 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1052 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1075 1053
1076 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1054 ASSERT_TRUE(this->op_->Decode());
1077 ASSERT_EQ(1U, this->op_->StackSize()); 1055 ASSERT_EQ(1U, this->op_->StackSize());
1078 1056
1079 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1057 ASSERT_FALSE(this->op_->Decode());
1080 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1058 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1081 1059
1082 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1060 ASSERT_TRUE(this->op_->Decode());
1083 ASSERT_EQ(2U, this->op_->StackSize()); 1061 ASSERT_EQ(2U, this->op_->StackSize());
1084 1062
1085 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1063 ASSERT_TRUE(this->op_->Decode());
1086 ASSERT_EQ(0x21, this->op_->cur_op()); 1064 ASSERT_EQ(0x21, this->op_->cur_op());
1087 ASSERT_EQ(1U, this->op_->StackSize()); 1065 ASSERT_EQ(1U, this->op_->StackSize());
1088 ASSERT_EQ(0xfcU, this->op_->StackAt(0)); 1066 ASSERT_EQ(0xfcU, this->op_->StackAt(0));
@@ -1101,19 +1079,19 @@ TYPED_TEST_P(DwarfOpTest, op_plus) {
1101 }; 1079 };
1102 this->op_memory_.SetMemory(0, opcode_buffer); 1080 this->op_memory_.SetMemory(0, opcode_buffer);
1103 1081
1104 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1082 ASSERT_FALSE(this->op_->Decode());
1105 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1083 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1106 1084
1107 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1085 ASSERT_TRUE(this->op_->Decode());
1108 ASSERT_EQ(1U, this->op_->StackSize()); 1086 ASSERT_EQ(1U, this->op_->StackSize());
1109 1087
1110 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1088 ASSERT_FALSE(this->op_->Decode());
1111 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1089 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1112 1090
1113 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1091 ASSERT_TRUE(this->op_->Decode());
1114 ASSERT_EQ(2U, this->op_->StackSize()); 1092 ASSERT_EQ(2U, this->op_->StackSize());
1115 1093
1116 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1094 ASSERT_TRUE(this->op_->Decode());
1117 ASSERT_EQ(0x22, this->op_->cur_op()); 1095 ASSERT_EQ(0x22, this->op_->cur_op());
1118 ASSERT_EQ(1U, this->op_->StackSize()); 1096 ASSERT_EQ(1U, this->op_->StackSize());
1119 ASSERT_EQ(0x1f1U, this->op_->StackAt(0)); 1097 ASSERT_EQ(0x1f1U, this->op_->StackAt(0));
@@ -1128,13 +1106,13 @@ TYPED_TEST_P(DwarfOpTest, op_plus_uconst) {
1128 }; 1106 };
1129 this->op_memory_.SetMemory(0, opcode_buffer); 1107 this->op_memory_.SetMemory(0, opcode_buffer);
1130 1108
1131 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1109 ASSERT_FALSE(this->op_->Decode());
1132 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1110 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1133 1111
1134 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1112 ASSERT_TRUE(this->op_->Decode());
1135 ASSERT_EQ(1U, this->op_->StackSize()); 1113 ASSERT_EQ(1U, this->op_->StackSize());
1136 1114
1137 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1115 ASSERT_TRUE(this->op_->Decode());
1138 ASSERT_EQ(0x23, this->op_->cur_op()); 1116 ASSERT_EQ(0x23, this->op_->cur_op());
1139 ASSERT_EQ(1U, this->op_->StackSize()); 1117 ASSERT_EQ(1U, this->op_->StackSize());
1140 ASSERT_EQ(0x28d0U, this->op_->StackAt(0)); 1118 ASSERT_EQ(0x28d0U, this->op_->StackAt(0));
@@ -1153,19 +1131,19 @@ TYPED_TEST_P(DwarfOpTest, op_shl) {
1153 }; 1131 };
1154 this->op_memory_.SetMemory(0, opcode_buffer); 1132 this->op_memory_.SetMemory(0, opcode_buffer);
1155 1133
1156 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1134 ASSERT_FALSE(this->op_->Decode());
1157 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1135 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1158 1136
1159 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1137 ASSERT_TRUE(this->op_->Decode());
1160 ASSERT_EQ(1U, this->op_->StackSize()); 1138 ASSERT_EQ(1U, this->op_->StackSize());
1161 1139
1162 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1140 ASSERT_FALSE(this->op_->Decode());
1163 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1141 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1164 1142
1165 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1143 ASSERT_TRUE(this->op_->Decode());
1166 ASSERT_EQ(2U, this->op_->StackSize()); 1144 ASSERT_EQ(2U, this->op_->StackSize());
1167 1145
1168 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1146 ASSERT_TRUE(this->op_->Decode());
1169 ASSERT_EQ(0x24, this->op_->cur_op()); 1147 ASSERT_EQ(0x24, this->op_->cur_op());
1170 ASSERT_EQ(1U, this->op_->StackSize()); 1148 ASSERT_EQ(1U, this->op_->StackSize());
1171 ASSERT_EQ(0x338U, this->op_->StackAt(0)); 1149 ASSERT_EQ(0x338U, this->op_->StackAt(0));
@@ -1184,19 +1162,19 @@ TYPED_TEST_P(DwarfOpTest, op_shr) {
1184 }; 1162 };
1185 this->op_memory_.SetMemory(0, opcode_buffer); 1163 this->op_memory_.SetMemory(0, opcode_buffer);
1186 1164
1187 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1165 ASSERT_FALSE(this->op_->Decode());
1188 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1166 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1189 1167
1190 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1168 ASSERT_TRUE(this->op_->Decode());
1191 ASSERT_EQ(1U, this->op_->StackSize()); 1169 ASSERT_EQ(1U, this->op_->StackSize());
1192 1170
1193 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1171 ASSERT_FALSE(this->op_->Decode());
1194 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1172 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1195 1173
1196 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1174 ASSERT_TRUE(this->op_->Decode());
1197 ASSERT_EQ(2U, this->op_->StackSize()); 1175 ASSERT_EQ(2U, this->op_->StackSize());
1198 1176
1199 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1177 ASSERT_TRUE(this->op_->Decode());
1200 ASSERT_EQ(0x25, this->op_->cur_op()); 1178 ASSERT_EQ(0x25, this->op_->cur_op());
1201 ASSERT_EQ(1U, this->op_->StackSize()); 1179 ASSERT_EQ(1U, this->op_->StackSize());
1202 if (sizeof(TypeParam) == 4) { 1180 if (sizeof(TypeParam) == 4) {
@@ -1219,19 +1197,19 @@ TYPED_TEST_P(DwarfOpTest, op_shra) {
1219 }; 1197 };
1220 this->op_memory_.SetMemory(0, opcode_buffer); 1198 this->op_memory_.SetMemory(0, opcode_buffer);
1221 1199
1222 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1200 ASSERT_FALSE(this->op_->Decode());
1223 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1201 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1224 1202
1225 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1203 ASSERT_TRUE(this->op_->Decode());
1226 ASSERT_EQ(1U, this->op_->StackSize()); 1204 ASSERT_EQ(1U, this->op_->StackSize());
1227 1205
1228 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1206 ASSERT_FALSE(this->op_->Decode());
1229 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1207 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1230 1208
1231 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1209 ASSERT_TRUE(this->op_->Decode());
1232 ASSERT_EQ(2U, this->op_->StackSize()); 1210 ASSERT_EQ(2U, this->op_->StackSize());
1233 1211
1234 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1212 ASSERT_TRUE(this->op_->Decode());
1235 ASSERT_EQ(0x26, this->op_->cur_op()); 1213 ASSERT_EQ(0x26, this->op_->cur_op());
1236 ASSERT_EQ(1U, this->op_->StackSize()); 1214 ASSERT_EQ(1U, this->op_->StackSize());
1237 ASSERT_EQ(static_cast<TypeParam>(-2), this->op_->StackAt(0)); 1215 ASSERT_EQ(static_cast<TypeParam>(-2), this->op_->StackAt(0));
@@ -1250,19 +1228,19 @@ TYPED_TEST_P(DwarfOpTest, op_xor) {
1250 }; 1228 };
1251 this->op_memory_.SetMemory(0, opcode_buffer); 1229 this->op_memory_.SetMemory(0, opcode_buffer);
1252 1230
1253 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1231 ASSERT_FALSE(this->op_->Decode());
1254 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1232 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1255 1233
1256 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1234 ASSERT_TRUE(this->op_->Decode());
1257 ASSERT_EQ(1U, this->op_->StackSize()); 1235 ASSERT_EQ(1U, this->op_->StackSize());
1258 1236
1259 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1237 ASSERT_FALSE(this->op_->Decode());
1260 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1238 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1261 1239
1262 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1240 ASSERT_TRUE(this->op_->Decode());
1263 ASSERT_EQ(2U, this->op_->StackSize()); 1241 ASSERT_EQ(2U, this->op_->StackSize());
1264 1242
1265 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1243 ASSERT_TRUE(this->op_->Decode());
1266 ASSERT_EQ(0x27, this->op_->cur_op()); 1244 ASSERT_EQ(0x27, this->op_->cur_op());
1267 ASSERT_EQ(1U, this->op_->StackSize()); 1245 ASSERT_EQ(1U, this->op_->StackSize());
1268 ASSERT_EQ(0x50U, this->op_->StackAt(0)); 1246 ASSERT_EQ(0x50U, this->op_->StackAt(0));
@@ -1283,48 +1261,48 @@ TYPED_TEST_P(DwarfOpTest, op_bra) {
1283 }; 1261 };
1284 this->op_memory_.SetMemory(0, opcode_buffer); 1262 this->op_memory_.SetMemory(0, opcode_buffer);
1285 1263
1286 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1264 ASSERT_FALSE(this->op_->Decode());
1287 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1265 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1288 1266
1289 // Push on a non-zero value with a positive branch. 1267 // Push on a non-zero value with a positive branch.
1290 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1268 ASSERT_TRUE(this->op_->Decode());
1291 ASSERT_EQ(1U, this->op_->StackSize()); 1269 ASSERT_EQ(1U, this->op_->StackSize());
1292 1270
1293 uint64_t offset = this->mem_->cur_offset() + 3; 1271 uint64_t offset = this->mem_->cur_offset() + 3;
1294 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1272 ASSERT_TRUE(this->op_->Decode());
1295 ASSERT_EQ(0x28, this->op_->cur_op()); 1273 ASSERT_EQ(0x28, this->op_->cur_op());
1296 ASSERT_EQ(0U, this->op_->StackSize()); 1274 ASSERT_EQ(0U, this->op_->StackSize());
1297 ASSERT_EQ(offset + 0x102, this->mem_->cur_offset()); 1275 ASSERT_EQ(offset + 0x102, this->mem_->cur_offset());
1298 1276
1299 // Push on a zero value with a positive branch. 1277 // Push on a zero value with a positive branch.
1300 this->mem_->set_cur_offset(offset); 1278 this->mem_->set_cur_offset(offset);
1301 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1279 ASSERT_TRUE(this->op_->Decode());
1302 ASSERT_EQ(1U, this->op_->StackSize()); 1280 ASSERT_EQ(1U, this->op_->StackSize());
1303 1281
1304 offset = this->mem_->cur_offset() + 3; 1282 offset = this->mem_->cur_offset() + 3;
1305 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1283 ASSERT_TRUE(this->op_->Decode());
1306 ASSERT_EQ(0x28, this->op_->cur_op()); 1284 ASSERT_EQ(0x28, this->op_->cur_op());
1307 ASSERT_EQ(0U, this->op_->StackSize()); 1285 ASSERT_EQ(0U, this->op_->StackSize());
1308 ASSERT_EQ(offset - 5, this->mem_->cur_offset()); 1286 ASSERT_EQ(offset - 5, this->mem_->cur_offset());
1309 1287
1310 // Push on a non-zero value with a negative branch. 1288 // Push on a non-zero value with a negative branch.
1311 this->mem_->set_cur_offset(offset); 1289 this->mem_->set_cur_offset(offset);
1312 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1290 ASSERT_TRUE(this->op_->Decode());
1313 ASSERT_EQ(1U, this->op_->StackSize()); 1291 ASSERT_EQ(1U, this->op_->StackSize());
1314 1292
1315 offset = this->mem_->cur_offset() + 3; 1293 offset = this->mem_->cur_offset() + 3;
1316 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1294 ASSERT_TRUE(this->op_->Decode());
1317 ASSERT_EQ(0x28, this->op_->cur_op()); 1295 ASSERT_EQ(0x28, this->op_->cur_op());
1318 ASSERT_EQ(0U, this->op_->StackSize()); 1296 ASSERT_EQ(0U, this->op_->StackSize());
1319 ASSERT_EQ(offset - 4, this->mem_->cur_offset()); 1297 ASSERT_EQ(offset - 4, this->mem_->cur_offset());
1320 1298
1321 // Push on a zero value with a negative branch. 1299 // Push on a zero value with a negative branch.
1322 this->mem_->set_cur_offset(offset); 1300 this->mem_->set_cur_offset(offset);
1323 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1301 ASSERT_TRUE(this->op_->Decode());
1324 ASSERT_EQ(1U, this->op_->StackSize()); 1302 ASSERT_EQ(1U, this->op_->StackSize());
1325 1303
1326 offset = this->mem_->cur_offset() + 3; 1304 offset = this->mem_->cur_offset() + 3;
1327 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1305 ASSERT_TRUE(this->op_->Decode());
1328 ASSERT_EQ(0x28, this->op_->cur_op()); 1306 ASSERT_EQ(0x28, this->op_->cur_op());
1329 ASSERT_EQ(0U, this->op_->StackSize()); 1307 ASSERT_EQ(0U, this->op_->StackSize());
1330 ASSERT_EQ(offset + 16, this->mem_->cur_offset()); 1308 ASSERT_EQ(offset + 16, this->mem_->cur_offset());
@@ -1344,11 +1322,11 @@ TYPED_TEST_P(DwarfOpTest, compare_opcode_stack_error) {
1344 opcode_buffer[3] = opcode; 1322 opcode_buffer[3] = opcode;
1345 this->op_memory_.SetMemory(0, opcode_buffer); 1323 this->op_memory_.SetMemory(0, opcode_buffer);
1346 1324
1347 ASSERT_FALSE(this->op_->Eval(0, 1, DWARF_VERSION_MAX)); 1325 ASSERT_FALSE(this->op_->Eval(0, 1));
1348 ASSERT_EQ(opcode, this->op_->cur_op()); 1326 ASSERT_EQ(opcode, this->op_->cur_op());
1349 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1327 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1350 1328
1351 ASSERT_FALSE(this->op_->Eval(1, 4, DWARF_VERSION_MAX)); 1329 ASSERT_FALSE(this->op_->Eval(1, 4));
1352 ASSERT_EQ(opcode, this->op_->cur_op()); 1330 ASSERT_EQ(opcode, this->op_->cur_op());
1353 ASSERT_EQ(1U, this->op_->StackSize()); 1331 ASSERT_EQ(1U, this->op_->StackSize());
1354 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); 1332 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
@@ -1387,7 +1365,7 @@ TYPED_TEST_P(DwarfOpTest, compare_opcodes) {
1387 opcode_buffer[14] = expected[i]; 1365 opcode_buffer[14] = expected[i];
1388 this->op_memory_.SetMemory(0, opcode_buffer); 1366 this->op_memory_.SetMemory(0, opcode_buffer);
1389 1367
1390 ASSERT_TRUE(this->op_->Eval(0, 15, DWARF_VERSION_MAX)) 1368 ASSERT_TRUE(this->op_->Eval(0, 15))
1391 << "Op: 0x" << std::hex << static_cast<uint32_t>(expected[i]) << " failed"; 1369 << "Op: 0x" << std::hex << static_cast<uint32_t>(expected[i]) << " failed";
1392 1370
1393 ASSERT_EQ(3U, this->op_->StackSize()); 1371 ASSERT_EQ(3U, this->op_->StackSize());
@@ -1407,14 +1385,14 @@ TYPED_TEST_P(DwarfOpTest, op_skip) {
1407 this->op_memory_.SetMemory(0, opcode_buffer); 1385 this->op_memory_.SetMemory(0, opcode_buffer);
1408 1386
1409 uint64_t offset = this->mem_->cur_offset() + 3; 1387 uint64_t offset = this->mem_->cur_offset() + 3;
1410 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1388 ASSERT_TRUE(this->op_->Decode());
1411 ASSERT_EQ(0x2f, this->op_->cur_op()); 1389 ASSERT_EQ(0x2f, this->op_->cur_op());
1412 ASSERT_EQ(0U, this->op_->StackSize()); 1390 ASSERT_EQ(0U, this->op_->StackSize());
1413 ASSERT_EQ(offset + 0x2010, this->mem_->cur_offset()); 1391 ASSERT_EQ(offset + 0x2010, this->mem_->cur_offset());
1414 1392
1415 this->mem_->set_cur_offset(offset); 1393 this->mem_->set_cur_offset(offset);
1416 offset = this->mem_->cur_offset() + 3; 1394 offset = this->mem_->cur_offset() + 3;
1417 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1395 ASSERT_TRUE(this->op_->Decode());
1418 ASSERT_EQ(0x2f, this->op_->cur_op()); 1396 ASSERT_EQ(0x2f, this->op_->cur_op());
1419 ASSERT_EQ(0U, this->op_->StackSize()); 1397 ASSERT_EQ(0U, this->op_->StackSize());
1420 ASSERT_EQ(offset - 3, this->mem_->cur_offset()); 1398 ASSERT_EQ(offset - 3, this->mem_->cur_offset());
@@ -1431,7 +1409,7 @@ TYPED_TEST_P(DwarfOpTest, op_lit) {
1431 1409
1432 for (size_t i = 0; i < opcode_buffer.size(); i++) { 1410 for (size_t i = 0; i < opcode_buffer.size(); i++) {
1433 uint32_t op = opcode_buffer[i]; 1411 uint32_t op = opcode_buffer[i];
1434 ASSERT_TRUE(this->op_->Eval(i, i + 1, DWARF_VERSION_MAX)) << "Failed op: 0x" << std::hex << op; 1412 ASSERT_TRUE(this->op_->Eval(i, i + 1)) << "Failed op: 0x" << std::hex << op;
1435 ASSERT_EQ(op, this->op_->cur_op()); 1413 ASSERT_EQ(op, this->op_->cur_op());
1436 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op; 1414 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
1437 ASSERT_EQ(op - 0x30U, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op; 1415 ASSERT_EQ(op - 0x30U, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
@@ -1449,7 +1427,7 @@ TYPED_TEST_P(DwarfOpTest, op_reg) {
1449 1427
1450 for (size_t i = 0; i < opcode_buffer.size(); i++) { 1428 for (size_t i = 0; i < opcode_buffer.size(); i++) {
1451 uint32_t op = opcode_buffer[i]; 1429 uint32_t op = opcode_buffer[i];
1452 ASSERT_TRUE(this->op_->Eval(i, i + 1, DWARF_VERSION_MAX)) << "Failed op: 0x" << std::hex << op; 1430 ASSERT_TRUE(this->op_->Eval(i, i + 1)) << "Failed op: 0x" << std::hex << op;
1453 ASSERT_EQ(op, this->op_->cur_op()); 1431 ASSERT_EQ(op, this->op_->cur_op());
1454 ASSERT_TRUE(this->op_->is_register()) << "Failed op: 0x" << std::hex << op; 1432 ASSERT_TRUE(this->op_->is_register()) << "Failed op: 0x" << std::hex << op;
1455 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op; 1433 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
@@ -1463,13 +1441,13 @@ TYPED_TEST_P(DwarfOpTest, op_regx) {
1463 }; 1441 };
1464 this->op_memory_.SetMemory(0, opcode_buffer); 1442 this->op_memory_.SetMemory(0, opcode_buffer);
1465 1443
1466 ASSERT_TRUE(this->op_->Eval(0, 2, DWARF_VERSION_MAX)); 1444 ASSERT_TRUE(this->op_->Eval(0, 2));
1467 ASSERT_EQ(0x90, this->op_->cur_op()); 1445 ASSERT_EQ(0x90, this->op_->cur_op());
1468 ASSERT_TRUE(this->op_->is_register()); 1446 ASSERT_TRUE(this->op_->is_register());
1469 ASSERT_EQ(1U, this->op_->StackSize()); 1447 ASSERT_EQ(1U, this->op_->StackSize());
1470 ASSERT_EQ(0x02U, this->op_->StackAt(0)); 1448 ASSERT_EQ(0x02U, this->op_->StackAt(0));
1471 1449
1472 ASSERT_TRUE(this->op_->Eval(2, 5, DWARF_VERSION_MAX)); 1450 ASSERT_TRUE(this->op_->Eval(2, 5));
1473 ASSERT_EQ(0x90, this->op_->cur_op()); 1451 ASSERT_EQ(0x90, this->op_->cur_op());
1474 ASSERT_TRUE(this->op_->is_register()); 1452 ASSERT_TRUE(this->op_->is_register());
1475 ASSERT_EQ(1U, this->op_->StackSize()); 1453 ASSERT_EQ(1U, this->op_->StackSize());
@@ -1494,21 +1472,20 @@ TYPED_TEST_P(DwarfOpTest, op_breg) {
1494 for (size_t i = 0; i < 32; i++) { 1472 for (size_t i = 0; i < 32; i++) {
1495 regs[i] = i + 10; 1473 regs[i] = i + 10;
1496 } 1474 }
1497 this->op_->set_regs(&regs); 1475 RegsInfo<TypeParam> regs_info(&regs);
1476 this->op_->set_regs_info(&regs_info);
1498 1477
1499 uint64_t offset = 0; 1478 uint64_t offset = 0;
1500 for (uint32_t op = 0x70; op <= 0x8f; op++) { 1479 for (uint32_t op = 0x70; op <= 0x8f; op++) {
1501 // Positive value added to register. 1480 // Positive value added to register.
1502 ASSERT_TRUE(this->op_->Eval(offset, offset + 2, DWARF_VERSION_MAX)) << "Failed op: 0x" 1481 ASSERT_TRUE(this->op_->Eval(offset, offset + 2)) << "Failed op: 0x" << std::hex << op;
1503 << std::hex << op;
1504 ASSERT_EQ(op, this->op_->cur_op()); 1482 ASSERT_EQ(op, this->op_->cur_op());
1505 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op; 1483 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
1506 ASSERT_EQ(op - 0x70 + 10 + 0x12, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op; 1484 ASSERT_EQ(op - 0x70 + 10 + 0x12, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
1507 offset += 2; 1485 offset += 2;
1508 1486
1509 // Negative value added to register. 1487 // Negative value added to register.
1510 ASSERT_TRUE(this->op_->Eval(offset, offset + 2, DWARF_VERSION_MAX)) << "Failed op: 0x" 1488 ASSERT_TRUE(this->op_->Eval(offset, offset + 2)) << "Failed op: 0x" << std::hex << op;
1511 << std::hex << op;
1512 ASSERT_EQ(op, this->op_->cur_op()); 1489 ASSERT_EQ(op, this->op_->cur_op());
1513 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op; 1490 ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
1514 ASSERT_EQ(op - 0x70 + 10 - 2, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op; 1491 ASSERT_EQ(op - 0x70 + 10 - 2, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
@@ -1526,16 +1503,17 @@ TYPED_TEST_P(DwarfOpTest, op_breg_invalid_register) {
1526 for (size_t i = 0; i < 16; i++) { 1503 for (size_t i = 0; i < 16; i++) {
1527 regs[i] = i + 10; 1504 regs[i] = i + 10;
1528 } 1505 }
1529 this->op_->set_regs(&regs); 1506 RegsInfo<TypeParam> regs_info(&regs);
1507 this->op_->set_regs_info(&regs_info);
1530 1508
1531 // Should pass since this references the last regsister. 1509 // Should pass since this references the last regsister.
1532 ASSERT_TRUE(this->op_->Eval(0, 2, DWARF_VERSION_MAX)); 1510 ASSERT_TRUE(this->op_->Eval(0, 2));
1533 ASSERT_EQ(0x7fU, this->op_->cur_op()); 1511 ASSERT_EQ(0x7fU, this->op_->cur_op());
1534 ASSERT_EQ(1U, this->op_->StackSize()); 1512 ASSERT_EQ(1U, this->op_->StackSize());
1535 ASSERT_EQ(0x2bU, this->op_->StackAt(0)); 1513 ASSERT_EQ(0x2bU, this->op_->StackAt(0));
1536 1514
1537 // Should fail since this references a non-existent register. 1515 // Should fail since this references a non-existent register.
1538 ASSERT_FALSE(this->op_->Eval(2, 4, DWARF_VERSION_MAX)); 1516 ASSERT_FALSE(this->op_->Eval(2, 4));
1539 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); 1517 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
1540} 1518}
1541 1519
@@ -1551,38 +1529,55 @@ TYPED_TEST_P(DwarfOpTest, op_bregx) {
1551 RegsImplFake<TypeParam> regs(10, 10); 1529 RegsImplFake<TypeParam> regs(10, 10);
1552 regs[5] = 0x45; 1530 regs[5] = 0x45;
1553 regs[6] = 0x190; 1531 regs[6] = 0x190;
1554 this->op_->set_regs(&regs); 1532 RegsInfo<TypeParam> regs_info(&regs);
1533 this->op_->set_regs_info(&regs_info);
1555 1534
1556 ASSERT_TRUE(this->op_->Eval(0, 3, DWARF_VERSION_MAX)); 1535 ASSERT_TRUE(this->op_->Eval(0, 3));
1557 ASSERT_EQ(0x92, this->op_->cur_op()); 1536 ASSERT_EQ(0x92, this->op_->cur_op());
1558 ASSERT_EQ(1U, this->op_->StackSize()); 1537 ASSERT_EQ(1U, this->op_->StackSize());
1559 ASSERT_EQ(0x65U, this->op_->StackAt(0)); 1538 ASSERT_EQ(0x65U, this->op_->StackAt(0));
1560 1539
1561 ASSERT_TRUE(this->op_->Eval(3, 7, DWARF_VERSION_MAX)); 1540 ASSERT_TRUE(this->op_->Eval(3, 7));
1562 ASSERT_EQ(0x92, this->op_->cur_op()); 1541 ASSERT_EQ(0x92, this->op_->cur_op());
1563 ASSERT_EQ(1U, this->op_->StackSize()); 1542 ASSERT_EQ(1U, this->op_->StackSize());
1564 ASSERT_EQ(0x90U, this->op_->StackAt(0)); 1543 ASSERT_EQ(0x90U, this->op_->StackAt(0));
1565 1544
1566 ASSERT_FALSE(this->op_->Eval(7, 12, DWARF_VERSION_MAX)); 1545 ASSERT_FALSE(this->op_->Eval(7, 12));
1567 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); 1546 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
1568} 1547}
1569 1548
1570TYPED_TEST_P(DwarfOpTest, op_nop) { 1549TYPED_TEST_P(DwarfOpTest, op_nop) {
1571 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96}); 1550 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96});
1572 1551
1573 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1552 ASSERT_TRUE(this->op_->Decode());
1574 ASSERT_EQ(0x96, this->op_->cur_op()); 1553 ASSERT_EQ(0x96, this->op_->cur_op());
1575 ASSERT_EQ(0U, this->op_->StackSize()); 1554 ASSERT_EQ(0U, this->op_->StackSize());
1576} 1555}
1577 1556
1578REGISTER_TYPED_TEST_CASE_P(DwarfOpTest, decode, eval, illegal_opcode, illegal_in_version3, 1557TYPED_TEST_P(DwarfOpTest, is_dex_pc) {
1579 illegal_in_version4, not_implemented, op_addr, op_deref, op_deref_size, 1558 // Special sequence that indicates this is a dex pc.
1580 const_unsigned, const_signed, const_uleb, const_sleb, op_dup, op_drop, 1559 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13});
1581 op_over, op_pick, op_swap, op_rot, op_abs, op_and, op_div, op_minus, 1560
1582 op_mod, op_mul, op_neg, op_not, op_or, op_plus, op_plus_uconst, op_shl, 1561 ASSERT_TRUE(this->op_->Eval(0, 6));
1583 op_shr, op_shra, op_xor, op_bra, compare_opcode_stack_error, 1562 EXPECT_TRUE(this->op_->dex_pc_set());
1584 compare_opcodes, op_skip, op_lit, op_reg, op_regx, op_breg, 1563
1585 op_breg_invalid_register, op_bregx, op_nop); 1564 // Try without the last op.
1565 ASSERT_TRUE(this->op_->Eval(0, 5));
1566 EXPECT_FALSE(this->op_->dex_pc_set());
1567
1568 // Change the constant.
1569 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '2', 0x13});
1570 ASSERT_TRUE(this->op_->Eval(0, 6));
1571 EXPECT_FALSE(this->op_->dex_pc_set());
1572}
1573
1574REGISTER_TYPED_TEST_CASE_P(DwarfOpTest, decode, eval, illegal_opcode, not_implemented, op_addr,
1575 op_deref, op_deref_size, const_unsigned, const_signed, const_uleb,
1576 const_sleb, op_dup, op_drop, op_over, op_pick, op_swap, op_rot, op_abs,
1577 op_and, op_div, op_minus, op_mod, op_mul, op_neg, op_not, op_or, op_plus,
1578 op_plus_uconst, op_shl, op_shr, op_shra, op_xor, op_bra,
1579 compare_opcode_stack_error, compare_opcodes, op_skip, op_lit, op_reg,
1580 op_regx, op_breg, op_breg_invalid_register, op_bregx, op_nop, is_dex_pc);
1586 1581
1587typedef ::testing::Types<uint32_t, uint64_t> DwarfOpTestTypes; 1582typedef ::testing::Types<uint32_t, uint64_t> DwarfOpTestTypes;
1588INSTANTIATE_TYPED_TEST_CASE_P(, DwarfOpTest, DwarfOpTestTypes); 1583INSTANTIATE_TYPED_TEST_CASE_P(, DwarfOpTest, DwarfOpTestTypes);
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index 7e10935eb..37305b26b 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -99,7 +99,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
99 regs.set_sp(0x2000); 99 regs.set_sp(0x2000);
100 regs[5] = 0x20; 100 regs[5] = 0x20;
101 regs[9] = 0x3000; 101 regs[9] = 0x3000;
102 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; 102 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5002}};
103 bool finished; 103 bool finished;
104 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 104 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
105 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode()); 105 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
@@ -116,7 +116,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
116 regs[5] = 0x20; 116 regs[5] = 0x20;
117 regs[9] = 0x3000; 117 regs[9] = 0x3000;
118 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96}); 118 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
119 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; 119 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5002}};
120 bool finished; 120 bool finished;
121 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 121 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
122 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode()); 122 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode());
@@ -134,7 +134,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
134 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80}); 134 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
135 TypeParam cfa_value = 0x12345; 135 TypeParam cfa_value = 0x12345;
136 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value)); 136 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
137 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}}; 137 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
138 bool finished; 138 bool finished;
139 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 139 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
140 EXPECT_FALSE(finished); 140 EXPECT_FALSE(finished);
@@ -152,7 +152,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
152 regs[5] = 0x20; 152 regs[5] = 0x20;
153 regs[9] = 0x3000; 153 regs[9] = 0x3000;
154 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80}); 154 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
155 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}}; 155 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
156 bool finished; 156 bool finished;
157 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 157 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
158 ASSERT_FALSE(finished); 158 ASSERT_FALSE(finished);
@@ -170,7 +170,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
170 regs[5] = 0x20; 170 regs[5] = 0x20;
171 regs[9] = 0x3000; 171 regs[9] = 0x3000;
172 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96}); 172 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
173 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; 173 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5002}};
174 bool finished; 174 bool finished;
175 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 175 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
176 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode()); 176 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode());
@@ -322,7 +322,8 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
322 regs[0] = 0x10; 322 regs[0] = 0x10;
323 regs[8] = 0x20; 323 regs[8] = 0x20;
324 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 324 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
325 loc_regs[0x20444558] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}}; 325 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x8, 0x5008}};
326 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13, 0x08, 0x11});
326 bool finished; 327 bool finished;
327 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 328 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
328 EXPECT_EQ(0x10U, regs[0]); 329 EXPECT_EQ(0x10U, regs[0]);
@@ -462,7 +463,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
462 TypeParam cfa_value = 0x12345; 463 TypeParam cfa_value = 0x12345;
463 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value)); 464 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
464 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 465 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
465 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}}; 466 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
466 bool finished; 467 bool finished;
467 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 468 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
468 EXPECT_FALSE(finished); 469 EXPECT_FALSE(finished);
@@ -480,7 +481,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
480 regs[8] = 0x3000; 481 regs[8] = 0x3000;
481 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80}); 482 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
482 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 483 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
483 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}}; 484 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
484 bool finished; 485 bool finished;
485 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 486 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
486 EXPECT_FALSE(finished); 487 EXPECT_FALSE(finished);
diff --git a/libunwindstack/tests/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp
index 0086c9edb..89331ea26 100644
--- a/libunwindstack/tests/ElfCacheTest.cpp
+++ b/libunwindstack/tests/ElfCacheTest.cpp
@@ -60,6 +60,7 @@ class ElfCacheTest : public ::testing::Test {
60 60
61 void VerifyWithinSameMap(bool cache_enabled); 61 void VerifyWithinSameMap(bool cache_enabled);
62 void VerifySameMap(bool cache_enabled); 62 void VerifySameMap(bool cache_enabled);
63 void VerifyWithinSameMapNeverReadAtZero(bool cache_enabled);
63 64
64 static std::shared_ptr<Memory> memory_; 65 static std::shared_ptr<Memory> memory_;
65}; 66};
@@ -198,4 +199,66 @@ TEST_F(ElfCacheTest, caching_valid_elf_offset_non_zero) {
198 VerifyWithinSameMap(true); 199 VerifyWithinSameMap(true);
199} 200}
200 201
202// Verify that when reading from multiple non-zero offsets in the same map
203// that when cached, all of the elf objects are the same.
204void ElfCacheTest::VerifyWithinSameMapNeverReadAtZero(bool cache_enabled) {
205 if (!cache_enabled) {
206 Elf::SetCachingEnabled(false);
207 }
208
209 TemporaryFile tf;
210 ASSERT_TRUE(tf.fd != -1);
211 WriteElfFile(0, &tf, EM_ARM);
212 lseek(tf.fd, 0x500, SEEK_SET);
213 uint8_t value = 0;
214 write(tf.fd, &value, 1);
215 close(tf.fd);
216
217 uint64_t start = 0x1000;
218 uint64_t end = 0x20000;
219 // Multiple info sections at different offsets will have non-zero elf offsets.
220 MapInfo info300_1(start, end, 0x300, 0x5, tf.path);
221 MapInfo info300_2(start, end, 0x300, 0x5, tf.path);
222 MapInfo info400_1(start, end, 0x400, 0x5, tf.path);
223 MapInfo info400_2(start, end, 0x400, 0x5, tf.path);
224
225 Elf* elf300_1 = info300_1.GetElf(memory_, true);
226 ASSERT_TRUE(elf300_1->valid());
227 EXPECT_EQ(ARCH_ARM, elf300_1->arch());
228 Elf* elf300_2 = info300_2.GetElf(memory_, true);
229 ASSERT_TRUE(elf300_2->valid());
230 EXPECT_EQ(ARCH_ARM, elf300_2->arch());
231 EXPECT_EQ(0x300U, info300_1.elf_offset);
232 EXPECT_EQ(0x300U, info300_2.elf_offset);
233 if (cache_enabled) {
234 EXPECT_EQ(elf300_1, elf300_2);
235 } else {
236 EXPECT_NE(elf300_1, elf300_2);
237 }
238
239 Elf* elf400_1 = info400_1.GetElf(memory_, true);
240 ASSERT_TRUE(elf400_1->valid());
241 EXPECT_EQ(ARCH_ARM, elf400_1->arch());
242 Elf* elf400_2 = info400_2.GetElf(memory_, true);
243 ASSERT_TRUE(elf400_2->valid());
244 EXPECT_EQ(ARCH_ARM, elf400_2->arch());
245 EXPECT_EQ(0x400U, info400_1.elf_offset);
246 EXPECT_EQ(0x400U, info400_2.elf_offset);
247 if (cache_enabled) {
248 EXPECT_EQ(elf400_1, elf400_2);
249 EXPECT_EQ(elf300_1, elf400_1);
250 } else {
251 EXPECT_NE(elf400_1, elf400_2);
252 EXPECT_NE(elf300_1, elf400_1);
253 }
254}
255
256TEST_F(ElfCacheTest, no_caching_valid_elf_offset_non_zero_never_read_at_zero) {
257 VerifyWithinSameMapNeverReadAtZero(false);
258}
259
260TEST_F(ElfCacheTest, caching_valid_elf_offset_non_zero_never_read_at_zero) {
261 VerifyWithinSameMapNeverReadAtZero(true);
262}
263
201} // namespace unwindstack 264} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index 042c5fb3b..bf97e30bf 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -63,15 +63,28 @@ class ElfInterfaceTest : public ::testing::Test {
63 template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> 63 template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
64 void ManyPhdrs(); 64 void ManyPhdrs();
65 65
66 template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> 66 enum SonameTestEnum : uint8_t {
67 SONAME_NORMAL,
68 SONAME_DTNULL_AFTER,
69 SONAME_DTSIZE_SMALL,
70 SONAME_MISSING_MAP,
71 };
72
73 template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn>
74 void SonameInit(SonameTestEnum test_type = SONAME_NORMAL);
75
76 template <typename ElfInterfaceType>
67 void Soname(); 77 void Soname();
68 78
69 template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> 79 template <typename ElfInterfaceType>
70 void SonameAfterDtNull(); 80 void SonameAfterDtNull();
71 81
72 template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> 82 template <typename ElfInterfaceType>
73 void SonameSize(); 83 void SonameSize();
74 84
85 template <typename ElfInterfaceType>
86 void SonameMissingMap();
87
75 template <typename ElfType> 88 template <typename ElfType>
76 void InitHeadersEhFrameTest(); 89 void InitHeadersEhFrameTest();
77 90
@@ -465,17 +478,29 @@ TEST_F(ElfInterfaceTest, elf32_arm) {
465 ASSERT_EQ(2U, elf_arm.total_entries()); 478 ASSERT_EQ(2U, elf_arm.total_entries());
466} 479}
467 480
468template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> 481template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn>
469void ElfInterfaceTest::Soname() { 482void ElfInterfaceTest::SonameInit(SonameTestEnum test_type) {
470 std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
471
472 Ehdr ehdr; 483 Ehdr ehdr;
473 memset(&ehdr, 0, sizeof(ehdr)); 484 memset(&ehdr, 0, sizeof(ehdr));
485 ehdr.e_shoff = 0x200;
486 ehdr.e_shnum = 2;
487 ehdr.e_shentsize = sizeof(Shdr);
474 ehdr.e_phoff = 0x100; 488 ehdr.e_phoff = 0x100;
475 ehdr.e_phnum = 1; 489 ehdr.e_phnum = 1;
476 ehdr.e_phentsize = sizeof(Phdr); 490 ehdr.e_phentsize = sizeof(Phdr);
477 memory_.SetMemory(0, &ehdr, sizeof(ehdr)); 491 memory_.SetMemory(0, &ehdr, sizeof(ehdr));
478 492
493 Shdr shdr;
494 memset(&shdr, 0, sizeof(shdr));
495 shdr.sh_type = SHT_STRTAB;
496 if (test_type == SONAME_MISSING_MAP) {
497 shdr.sh_addr = 0x20100;
498 } else {
499 shdr.sh_addr = 0x10100;
500 }
501 shdr.sh_offset = 0x10000;
502 memory_.SetMemory(0x200 + sizeof(shdr), &shdr, sizeof(shdr));
503
479 Phdr phdr; 504 Phdr phdr;
480 memset(&phdr, 0, sizeof(phdr)); 505 memset(&phdr, 0, sizeof(phdr));
481 phdr.p_type = PT_DYNAMIC; 506 phdr.p_type = PT_DYNAMIC;
@@ -487,15 +512,25 @@ void ElfInterfaceTest::Soname() {
487 Dyn dyn; 512 Dyn dyn;
488 513
489 dyn.d_tag = DT_STRTAB; 514 dyn.d_tag = DT_STRTAB;
490 dyn.d_un.d_ptr = 0x10000; 515 dyn.d_un.d_ptr = 0x10100;
491 memory_.SetMemory(offset, &dyn, sizeof(dyn)); 516 memory_.SetMemory(offset, &dyn, sizeof(dyn));
492 offset += sizeof(dyn); 517 offset += sizeof(dyn);
493 518
494 dyn.d_tag = DT_STRSZ; 519 dyn.d_tag = DT_STRSZ;
495 dyn.d_un.d_val = 0x1000; 520 if (test_type == SONAME_DTSIZE_SMALL) {
521 dyn.d_un.d_val = 0x10;
522 } else {
523 dyn.d_un.d_val = 0x1000;
524 }
496 memory_.SetMemory(offset, &dyn, sizeof(dyn)); 525 memory_.SetMemory(offset, &dyn, sizeof(dyn));
497 offset += sizeof(dyn); 526 offset += sizeof(dyn);
498 527
528 if (test_type == SONAME_DTNULL_AFTER) {
529 dyn.d_tag = DT_NULL;
530 memory_.SetMemory(offset, &dyn, sizeof(dyn));
531 offset += sizeof(dyn);
532 }
533
499 dyn.d_tag = DT_SONAME; 534 dyn.d_tag = DT_SONAME;
500 dyn.d_un.d_val = 0x10; 535 dyn.d_un.d_val = 0x10;
501 memory_.SetMemory(offset, &dyn, sizeof(dyn)); 536 memory_.SetMemory(offset, &dyn, sizeof(dyn));
@@ -505,6 +540,11 @@ void ElfInterfaceTest::Soname() {
505 memory_.SetMemory(offset, &dyn, sizeof(dyn)); 540 memory_.SetMemory(offset, &dyn, sizeof(dyn));
506 541
507 SetStringMemory(0x10010, "fake_soname.so"); 542 SetStringMemory(0x10010, "fake_soname.so");
543}
544
545template <typename ElfInterfaceType>
546void ElfInterfaceTest::Soname() {
547 std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
508 548
509 uint64_t load_bias = 0; 549 uint64_t load_bias = 0;
510 ASSERT_TRUE(elf->Init(&load_bias)); 550 ASSERT_TRUE(elf->Init(&load_bias));
@@ -516,55 +556,19 @@ void ElfInterfaceTest::Soname() {
516} 556}
517 557
518TEST_F(ElfInterfaceTest, elf32_soname) { 558TEST_F(ElfInterfaceTest, elf32_soname) {
519 Soname<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>(); 559 SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>();
560 Soname<ElfInterface32>();
520} 561}
521 562
522TEST_F(ElfInterfaceTest, elf64_soname) { 563TEST_F(ElfInterfaceTest, elf64_soname) {
523 Soname<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>(); 564 SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>();
565 Soname<ElfInterface64>();
524} 566}
525 567
526template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> 568template <typename ElfInterfaceType>
527void ElfInterfaceTest::SonameAfterDtNull() { 569void ElfInterfaceTest::SonameAfterDtNull() {
528 std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); 570 std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
529 571
530 Ehdr ehdr;
531 memset(&ehdr, 0, sizeof(ehdr));
532 ehdr.e_phoff = 0x100;
533 ehdr.e_phnum = 1;
534 ehdr.e_phentsize = sizeof(Phdr);
535 memory_.SetMemory(0, &ehdr, sizeof(ehdr));
536
537 Phdr phdr;
538 memset(&phdr, 0, sizeof(phdr));
539 phdr.p_type = PT_DYNAMIC;
540 phdr.p_offset = 0x2000;
541 phdr.p_memsz = sizeof(Dyn) * 3;
542 memory_.SetMemory(0x100, &phdr, sizeof(phdr));
543
544 Dyn dyn;
545 uint64_t offset = 0x2000;
546
547 dyn.d_tag = DT_STRTAB;
548 dyn.d_un.d_ptr = 0x10000;
549 memory_.SetMemory(offset, &dyn, sizeof(dyn));
550 offset += sizeof(dyn);
551
552 dyn.d_tag = DT_STRSZ;
553 dyn.d_un.d_val = 0x1000;
554 memory_.SetMemory(offset, &dyn, sizeof(dyn));
555 offset += sizeof(dyn);
556
557 dyn.d_tag = DT_NULL;
558 memory_.SetMemory(offset, &dyn, sizeof(dyn));
559 offset += sizeof(dyn);
560
561 dyn.d_tag = DT_SONAME;
562 dyn.d_un.d_val = 0x10;
563 memory_.SetMemory(offset, &dyn, sizeof(dyn));
564 offset += sizeof(dyn);
565
566 SetStringMemory(0x10010, "fake_soname.so");
567
568 uint64_t load_bias = 0; 572 uint64_t load_bias = 0;
569 ASSERT_TRUE(elf->Init(&load_bias)); 573 ASSERT_TRUE(elf->Init(&load_bias));
570 EXPECT_EQ(0U, load_bias); 574 EXPECT_EQ(0U, load_bias);
@@ -574,53 +578,42 @@ void ElfInterfaceTest::SonameAfterDtNull() {
574} 578}
575 579
576TEST_F(ElfInterfaceTest, elf32_soname_after_dt_null) { 580TEST_F(ElfInterfaceTest, elf32_soname_after_dt_null) {
577 SonameAfterDtNull<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>(); 581 SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTNULL_AFTER);
582 SonameAfterDtNull<ElfInterface32>();
578} 583}
579 584
580TEST_F(ElfInterfaceTest, elf64_soname_after_dt_null) { 585TEST_F(ElfInterfaceTest, elf64_soname_after_dt_null) {
581 SonameAfterDtNull<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>(); 586 SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTNULL_AFTER);
587 SonameAfterDtNull<ElfInterface64>();
582} 588}
583 589
584template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> 590template <typename ElfInterfaceType>
585void ElfInterfaceTest::SonameSize() { 591void ElfInterfaceTest::SonameSize() {
586 std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); 592 std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
587 593
588 Ehdr ehdr; 594 uint64_t load_bias = 0;
589 memset(&ehdr, 0, sizeof(ehdr)); 595 ASSERT_TRUE(elf->Init(&load_bias));
590 ehdr.e_phoff = 0x100; 596 EXPECT_EQ(0U, load_bias);
591 ehdr.e_phnum = 1;
592 ehdr.e_phentsize = sizeof(Phdr);
593 memory_.SetMemory(0, &ehdr, sizeof(ehdr));
594
595 Phdr phdr;
596 memset(&phdr, 0, sizeof(phdr));
597 phdr.p_type = PT_DYNAMIC;
598 phdr.p_offset = 0x2000;
599 phdr.p_memsz = sizeof(Dyn);
600 memory_.SetMemory(0x100, &phdr, sizeof(phdr));
601
602 Dyn dyn;
603 uint64_t offset = 0x2000;
604
605 dyn.d_tag = DT_STRTAB;
606 dyn.d_un.d_ptr = 0x10000;
607 memory_.SetMemory(offset, &dyn, sizeof(dyn));
608 offset += sizeof(dyn);
609 597
610 dyn.d_tag = DT_STRSZ; 598 std::string name;
611 dyn.d_un.d_val = 0x10; 599 ASSERT_FALSE(elf->GetSoname(&name));
612 memory_.SetMemory(offset, &dyn, sizeof(dyn)); 600}
613 offset += sizeof(dyn);
614 601
615 dyn.d_tag = DT_SONAME; 602TEST_F(ElfInterfaceTest, elf32_soname_size) {
616 dyn.d_un.d_val = 0x10; 603 SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTSIZE_SMALL);
617 memory_.SetMemory(offset, &dyn, sizeof(dyn)); 604 SonameSize<ElfInterface32>();
618 offset += sizeof(dyn); 605}
619 606
620 dyn.d_tag = DT_NULL; 607TEST_F(ElfInterfaceTest, elf64_soname_size) {
621 memory_.SetMemory(offset, &dyn, sizeof(dyn)); 608 SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTSIZE_SMALL);
609 SonameSize<ElfInterface64>();
610}
622 611
623 SetStringMemory(0x10010, "fake_soname.so"); 612// Verify that there is no map from STRTAB in the dynamic section to a
613// STRTAB entry in the section headers.
614template <typename ElfInterfaceType>
615void ElfInterfaceTest::SonameMissingMap() {
616 std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
624 617
625 uint64_t load_bias = 0; 618 uint64_t load_bias = 0;
626 ASSERT_TRUE(elf->Init(&load_bias)); 619 ASSERT_TRUE(elf->Init(&load_bias));
@@ -630,12 +623,14 @@ void ElfInterfaceTest::SonameSize() {
630 ASSERT_FALSE(elf->GetSoname(&name)); 623 ASSERT_FALSE(elf->GetSoname(&name));
631} 624}
632 625
633TEST_F(ElfInterfaceTest, elf32_soname_size) { 626TEST_F(ElfInterfaceTest, elf32_soname_missing_map) {
634 SonameSize<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>(); 627 SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_MISSING_MAP);
628 SonameMissingMap<ElfInterface32>();
635} 629}
636 630
637TEST_F(ElfInterfaceTest, elf64_soname_size) { 631TEST_F(ElfInterfaceTest, elf64_soname_missing_map) {
638 SonameSize<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>(); 632 SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_MISSING_MAP);
633 SonameMissingMap<ElfInterface64>();
639} 634}
640 635
641template <typename ElfType> 636template <typename ElfType>
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index cd7f2ff2b..ab23194e5 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -47,7 +47,7 @@ class RegsFake : public Regs {
47 47
48 bool Is32Bit() { return false; } 48 bool Is32Bit() { return false; }
49 49
50 uint64_t GetAdjustedPc(uint64_t rel_pc, Elf*) override { return rel_pc - 2; } 50 uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 2; }
51 51
52 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } 52 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
53 53
@@ -77,7 +77,7 @@ class RegsImplFake : public RegsImpl<TypeParam> {
77 77
78 ArchEnum Arch() override { return ARCH_UNKNOWN; } 78 ArchEnum Arch() override { return ARCH_UNKNOWN; }
79 79
80 uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; } 80 uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 0; }
81 void SetFromRaw() override {} 81 void SetFromRaw() override {}
82 bool SetPcFromReturnAddress(Memory*) override { return false; } 82 bool SetPcFromReturnAddress(Memory*) override { return false; }
83 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } 83 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 7c063739d..8b2f6c83f 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -96,48 +96,48 @@ TEST_F(RegsTest, regs64) {
96 96
97TEST_F(RegsTest, rel_pc) { 97TEST_F(RegsTest, rel_pc) {
98 RegsArm64 arm64; 98 RegsArm64 arm64;
99 ASSERT_EQ(0xcU, arm64.GetAdjustedPc(0x10, elf_.get())); 99 ASSERT_EQ(4U, arm64.GetPcAdjustment(0x10, elf_.get()));
100 ASSERT_EQ(0x0U, arm64.GetAdjustedPc(0x4, elf_.get())); 100 ASSERT_EQ(4U, arm64.GetPcAdjustment(0x4, elf_.get()));
101 ASSERT_EQ(0x3U, arm64.GetAdjustedPc(0x3, elf_.get())); 101 ASSERT_EQ(0U, arm64.GetPcAdjustment(0x3, elf_.get()));
102 ASSERT_EQ(0x2U, arm64.GetAdjustedPc(0x2, elf_.get())); 102 ASSERT_EQ(0U, arm64.GetPcAdjustment(0x2, elf_.get()));
103 ASSERT_EQ(0x1U, arm64.GetAdjustedPc(0x1, elf_.get())); 103 ASSERT_EQ(0U, arm64.GetPcAdjustment(0x1, elf_.get()));
104 ASSERT_EQ(0x0U, arm64.GetAdjustedPc(0x0, elf_.get())); 104 ASSERT_EQ(0U, arm64.GetPcAdjustment(0x0, elf_.get()));
105 105
106 RegsX86 x86; 106 RegsX86 x86;
107 ASSERT_EQ(0xffU, x86.GetAdjustedPc(0x100, elf_.get())); 107 ASSERT_EQ(1U, x86.GetPcAdjustment(0x100, elf_.get()));
108 ASSERT_EQ(0x1U, x86.GetAdjustedPc(0x2, elf_.get())); 108 ASSERT_EQ(1U, x86.GetPcAdjustment(0x2, elf_.get()));
109 ASSERT_EQ(0x0U, x86.GetAdjustedPc(0x1, elf_.get())); 109 ASSERT_EQ(1U, x86.GetPcAdjustment(0x1, elf_.get()));
110 ASSERT_EQ(0x0U, x86.GetAdjustedPc(0x0, elf_.get())); 110 ASSERT_EQ(0U, x86.GetPcAdjustment(0x0, elf_.get()));
111 111
112 RegsX86_64 x86_64; 112 RegsX86_64 x86_64;
113 ASSERT_EQ(0xffU, x86_64.GetAdjustedPc(0x100, elf_.get())); 113 ASSERT_EQ(1U, x86_64.GetPcAdjustment(0x100, elf_.get()));
114 ASSERT_EQ(0x1U, x86_64.GetAdjustedPc(0x2, elf_.get())); 114 ASSERT_EQ(1U, x86_64.GetPcAdjustment(0x2, elf_.get()));
115 ASSERT_EQ(0x0U, x86_64.GetAdjustedPc(0x1, elf_.get())); 115 ASSERT_EQ(1U, x86_64.GetPcAdjustment(0x1, elf_.get()));
116 ASSERT_EQ(0x0U, x86_64.GetAdjustedPc(0x0, elf_.get())); 116 ASSERT_EQ(0U, x86_64.GetPcAdjustment(0x0, elf_.get()));
117 117
118 RegsMips mips; 118 RegsMips mips;
119 ASSERT_EQ(0x8U, mips.GetAdjustedPc(0x10, elf_.get())); 119 ASSERT_EQ(8U, mips.GetPcAdjustment(0x10, elf_.get()));
120 ASSERT_EQ(0x0U, mips.GetAdjustedPc(0x8, elf_.get())); 120 ASSERT_EQ(8U, mips.GetPcAdjustment(0x8, elf_.get()));
121 ASSERT_EQ(0x7U, mips.GetAdjustedPc(0x7, elf_.get())); 121 ASSERT_EQ(0U, mips.GetPcAdjustment(0x7, elf_.get()));
122 ASSERT_EQ(0x6U, mips.GetAdjustedPc(0x6, elf_.get())); 122 ASSERT_EQ(0U, mips.GetPcAdjustment(0x6, elf_.get()));
123 ASSERT_EQ(0x5U, mips.GetAdjustedPc(0x5, elf_.get())); 123 ASSERT_EQ(0U, mips.GetPcAdjustment(0x5, elf_.get()));
124 ASSERT_EQ(0x4U, mips.GetAdjustedPc(0x4, elf_.get())); 124 ASSERT_EQ(0U, mips.GetPcAdjustment(0x4, elf_.get()));
125 ASSERT_EQ(0x3U, mips.GetAdjustedPc(0x3, elf_.get())); 125 ASSERT_EQ(0U, mips.GetPcAdjustment(0x3, elf_.get()));
126 ASSERT_EQ(0x2U, mips.GetAdjustedPc(0x2, elf_.get())); 126 ASSERT_EQ(0U, mips.GetPcAdjustment(0x2, elf_.get()));
127 ASSERT_EQ(0x1U, mips.GetAdjustedPc(0x1, elf_.get())); 127 ASSERT_EQ(0U, mips.GetPcAdjustment(0x1, elf_.get()));
128 ASSERT_EQ(0x0U, mips.GetAdjustedPc(0x0, elf_.get())); 128 ASSERT_EQ(0U, mips.GetPcAdjustment(0x0, elf_.get()));
129 129
130 RegsMips64 mips64; 130 RegsMips64 mips64;
131 ASSERT_EQ(0x8U, mips64.GetAdjustedPc(0x10, elf_.get())); 131 ASSERT_EQ(8U, mips64.GetPcAdjustment(0x10, elf_.get()));
132 ASSERT_EQ(0x0U, mips64.GetAdjustedPc(0x8, elf_.get())); 132 ASSERT_EQ(8U, mips64.GetPcAdjustment(0x8, elf_.get()));
133 ASSERT_EQ(0x7U, mips64.GetAdjustedPc(0x7, elf_.get())); 133 ASSERT_EQ(0U, mips64.GetPcAdjustment(0x7, elf_.get()));
134 ASSERT_EQ(0x6U, mips64.GetAdjustedPc(0x6, elf_.get())); 134 ASSERT_EQ(0U, mips64.GetPcAdjustment(0x6, elf_.get()));
135 ASSERT_EQ(0x5U, mips64.GetAdjustedPc(0x5, elf_.get())); 135 ASSERT_EQ(0U, mips64.GetPcAdjustment(0x5, elf_.get()));
136 ASSERT_EQ(0x4U, mips64.GetAdjustedPc(0x4, elf_.get())); 136 ASSERT_EQ(0U, mips64.GetPcAdjustment(0x4, elf_.get()));
137 ASSERT_EQ(0x3U, mips64.GetAdjustedPc(0x3, elf_.get())); 137 ASSERT_EQ(0U, mips64.GetPcAdjustment(0x3, elf_.get()));
138 ASSERT_EQ(0x2U, mips64.GetAdjustedPc(0x2, elf_.get())); 138 ASSERT_EQ(0U, mips64.GetPcAdjustment(0x2, elf_.get()));
139 ASSERT_EQ(0x1U, mips64.GetAdjustedPc(0x1, elf_.get())); 139 ASSERT_EQ(0U, mips64.GetPcAdjustment(0x1, elf_.get()));
140 ASSERT_EQ(0x0U, mips64.GetAdjustedPc(0x0, elf_.get())); 140 ASSERT_EQ(0U, mips64.GetPcAdjustment(0x0, elf_.get()));
141} 141}
142 142
143TEST_F(RegsTest, rel_pc_arm) { 143TEST_F(RegsTest, rel_pc_arm) {
@@ -145,34 +145,34 @@ TEST_F(RegsTest, rel_pc_arm) {
145 145
146 // Check fence posts. 146 // Check fence posts.
147 elf_->FakeSetLoadBias(0); 147 elf_->FakeSetLoadBias(0);
148 ASSERT_EQ(3U, arm.GetAdjustedPc(0x5, elf_.get())); 148 ASSERT_EQ(2U, arm.GetPcAdjustment(0x5, elf_.get()));
149 ASSERT_EQ(4U, arm.GetAdjustedPc(0x4, elf_.get())); 149 ASSERT_EQ(0U, arm.GetPcAdjustment(0x4, elf_.get()));
150 ASSERT_EQ(3U, arm.GetAdjustedPc(0x3, elf_.get())); 150 ASSERT_EQ(0U, arm.GetPcAdjustment(0x3, elf_.get()));
151 ASSERT_EQ(2U, arm.GetAdjustedPc(0x2, elf_.get())); 151 ASSERT_EQ(0U, arm.GetPcAdjustment(0x2, elf_.get()));
152 ASSERT_EQ(1U, arm.GetAdjustedPc(0x1, elf_.get())); 152 ASSERT_EQ(0U, arm.GetPcAdjustment(0x1, elf_.get()));
153 ASSERT_EQ(0U, arm.GetAdjustedPc(0x0, elf_.get())); 153 ASSERT_EQ(0U, arm.GetPcAdjustment(0x0, elf_.get()));
154 154
155 elf_->FakeSetLoadBias(0x100); 155 elf_->FakeSetLoadBias(0x100);
156 ASSERT_EQ(0xffU, arm.GetAdjustedPc(0xff, elf_.get())); 156 ASSERT_EQ(0U, arm.GetPcAdjustment(0xff, elf_.get()));
157 ASSERT_EQ(0x103U, arm.GetAdjustedPc(0x105, elf_.get())); 157 ASSERT_EQ(2U, arm.GetPcAdjustment(0x105, elf_.get()));
158 ASSERT_EQ(0x104U, arm.GetAdjustedPc(0x104, elf_.get())); 158 ASSERT_EQ(0U, arm.GetPcAdjustment(0x104, elf_.get()));
159 ASSERT_EQ(0x103U, arm.GetAdjustedPc(0x103, elf_.get())); 159 ASSERT_EQ(0U, arm.GetPcAdjustment(0x103, elf_.get()));
160 ASSERT_EQ(0x102U, arm.GetAdjustedPc(0x102, elf_.get())); 160 ASSERT_EQ(0U, arm.GetPcAdjustment(0x102, elf_.get()));
161 ASSERT_EQ(0x101U, arm.GetAdjustedPc(0x101, elf_.get())); 161 ASSERT_EQ(0U, arm.GetPcAdjustment(0x101, elf_.get()));
162 ASSERT_EQ(0x100U, arm.GetAdjustedPc(0x100, elf_.get())); 162 ASSERT_EQ(0U, arm.GetPcAdjustment(0x100, elf_.get()));
163 163
164 // Check thumb instructions handling. 164 // Check thumb instructions handling.
165 elf_->FakeSetLoadBias(0); 165 elf_->FakeSetLoadBias(0);
166 memory_->SetData32(0x2000, 0); 166 memory_->SetData32(0x2000, 0);
167 ASSERT_EQ(0x2003U, arm.GetAdjustedPc(0x2005, elf_.get())); 167 ASSERT_EQ(2U, arm.GetPcAdjustment(0x2005, elf_.get()));
168 memory_->SetData32(0x2000, 0xe000f000); 168 memory_->SetData32(0x2000, 0xe000f000);
169 ASSERT_EQ(0x2001U, arm.GetAdjustedPc(0x2005, elf_.get())); 169 ASSERT_EQ(4U, arm.GetPcAdjustment(0x2005, elf_.get()));
170 170
171 elf_->FakeSetLoadBias(0x400); 171 elf_->FakeSetLoadBias(0x400);
172 memory_->SetData32(0x2100, 0); 172 memory_->SetData32(0x2100, 0);
173 ASSERT_EQ(0x2503U, arm.GetAdjustedPc(0x2505, elf_.get())); 173 ASSERT_EQ(2U, arm.GetPcAdjustment(0x2505, elf_.get()));
174 memory_->SetData32(0x2100, 0xf111f111); 174 memory_->SetData32(0x2100, 0xf111f111);
175 ASSERT_EQ(0x2501U, arm.GetAdjustedPc(0x2505, elf_.get())); 175 ASSERT_EQ(4U, arm.GetPcAdjustment(0x2505, elf_.get()));
176} 176}
177 177
178TEST_F(RegsTest, elf_invalid) { 178TEST_F(RegsTest, elf_invalid) {
@@ -188,27 +188,27 @@ TEST_F(RegsTest, elf_invalid) {
188 188
189 regs_arm.set_pc(0x1500); 189 regs_arm.set_pc(0x1500);
190 EXPECT_EQ(0x500U, invalid_elf->GetRelPc(regs_arm.pc(), &map_info)); 190 EXPECT_EQ(0x500U, invalid_elf->GetRelPc(regs_arm.pc(), &map_info));
191 EXPECT_EQ(0x4fcU, regs_arm.GetAdjustedPc(0x500U, invalid_elf)); 191 EXPECT_EQ(4U, regs_arm.GetPcAdjustment(0x500U, invalid_elf));
192 192
193 regs_arm64.set_pc(0x1600); 193 regs_arm64.set_pc(0x1600);
194 EXPECT_EQ(0x600U, invalid_elf->GetRelPc(regs_arm64.pc(), &map_info)); 194 EXPECT_EQ(0x600U, invalid_elf->GetRelPc(regs_arm64.pc(), &map_info));
195 EXPECT_EQ(0x600U, regs_arm64.GetAdjustedPc(0x600U, invalid_elf)); 195 EXPECT_EQ(0U, regs_arm64.GetPcAdjustment(0x600U, invalid_elf));
196 196
197 regs_x86.set_pc(0x1700); 197 regs_x86.set_pc(0x1700);
198 EXPECT_EQ(0x700U, invalid_elf->GetRelPc(regs_x86.pc(), &map_info)); 198 EXPECT_EQ(0x700U, invalid_elf->GetRelPc(regs_x86.pc(), &map_info));
199 EXPECT_EQ(0x700U, regs_x86.GetAdjustedPc(0x700U, invalid_elf)); 199 EXPECT_EQ(0U, regs_x86.GetPcAdjustment(0x700U, invalid_elf));
200 200
201 regs_x86_64.set_pc(0x1800); 201 regs_x86_64.set_pc(0x1800);
202 EXPECT_EQ(0x800U, invalid_elf->GetRelPc(regs_x86_64.pc(), &map_info)); 202 EXPECT_EQ(0x800U, invalid_elf->GetRelPc(regs_x86_64.pc(), &map_info));
203 EXPECT_EQ(0x800U, regs_x86_64.GetAdjustedPc(0x800U, invalid_elf)); 203 EXPECT_EQ(0U, regs_x86_64.GetPcAdjustment(0x800U, invalid_elf));
204 204
205 regs_mips.set_pc(0x1900); 205 regs_mips.set_pc(0x1900);
206 EXPECT_EQ(0x900U, invalid_elf->GetRelPc(regs_mips.pc(), &map_info)); 206 EXPECT_EQ(0x900U, invalid_elf->GetRelPc(regs_mips.pc(), &map_info));
207 EXPECT_EQ(0x900U, regs_mips.GetAdjustedPc(0x900U, invalid_elf)); 207 EXPECT_EQ(0U, regs_mips.GetPcAdjustment(0x900U, invalid_elf));
208 208
209 regs_mips64.set_pc(0x1a00); 209 regs_mips64.set_pc(0x1a00);
210 EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(regs_mips64.pc(), &map_info)); 210 EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(regs_mips64.pc(), &map_info));
211 EXPECT_EQ(0xa00U, regs_mips64.GetAdjustedPc(0xa00U, invalid_elf)); 211 EXPECT_EQ(0U, regs_mips64.GetPcAdjustment(0xa00U, invalid_elf));
212} 212}
213 213
214TEST_F(RegsTest, arm_set_from_raw) { 214TEST_F(RegsTest, arm_set_from_raw) {
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index df262f525..af4a5b59e 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -193,6 +193,14 @@ TEST_F(UnwindOfflineTest, pc_straddle_arm) {
193 " #02 pc 00007441 libbase.so (_ZN7android4base10LogMessageD2Ev+748)\n" 193 " #02 pc 00007441 libbase.so (_ZN7android4base10LogMessageD2Ev+748)\n"
194 " #03 pc 00015147 /does/not/exist/libhidlbase.so\n", 194 " #03 pc 00015147 /does/not/exist/libhidlbase.so\n",
195 frame_info); 195 frame_info);
196 EXPECT_EQ(0xf31ea9f8U, unwinder.frames()[0].pc);
197 EXPECT_EQ(0xe9c866f8U, unwinder.frames()[0].sp);
198 EXPECT_EQ(0xf2da0a1bU, unwinder.frames()[1].pc);
199 EXPECT_EQ(0xe9c86728U, unwinder.frames()[1].sp);
200 EXPECT_EQ(0xf2da1441U, unwinder.frames()[2].pc);
201 EXPECT_EQ(0xe9c86730U, unwinder.frames()[2].sp);
202 EXPECT_EQ(0xf3367147U, unwinder.frames()[3].pc);
203 EXPECT_EQ(0xe9c86778U, unwinder.frames()[3].sp);
196} 204}
197 205
198TEST_F(UnwindOfflineTest, pc_in_gnu_debugdata_arm) { 206TEST_F(UnwindOfflineTest, pc_in_gnu_debugdata_arm) {
@@ -209,6 +217,10 @@ TEST_F(UnwindOfflineTest, pc_in_gnu_debugdata_arm) {
209 " #01 pc 0006dce5 libandroid_runtime.so " 217 " #01 pc 0006dce5 libandroid_runtime.so "
210 "(_ZN7android14AndroidRuntime19javaCreateThreadEtcEPFiPvES1_PKcijPS1_)\n", 218 "(_ZN7android14AndroidRuntime19javaCreateThreadEtcEPFiPvES1_PKcijPS1_)\n",
211 frame_info); 219 frame_info);
220 EXPECT_EQ(0xf1f6dc49U, unwinder.frames()[0].pc);
221 EXPECT_EQ(0xd8fe6930U, unwinder.frames()[0].sp);
222 EXPECT_EQ(0xf1f6dce5U, unwinder.frames()[1].pc);
223 EXPECT_EQ(0xd8fe6958U, unwinder.frames()[1].sp);
212} 224}
213 225
214TEST_F(UnwindOfflineTest, pc_straddle_arm64) { 226TEST_F(UnwindOfflineTest, pc_straddle_arm64) {
@@ -229,6 +241,18 @@ TEST_F(UnwindOfflineTest, pc_straddle_arm64) {
229 "(_ZN11unwindstack37UnwindTest_remote_through_signal_Test8TestBodyEv+32)\n" 241 "(_ZN11unwindstack37UnwindTest_remote_through_signal_Test8TestBodyEv+32)\n"
230 " #05 pc 0000000000455d70 libunwindstack_test (_ZN7testing4Test3RunEv+392)\n", 242 " #05 pc 0000000000455d70 libunwindstack_test (_ZN7testing4Test3RunEv+392)\n",
231 frame_info); 243 frame_info);
244 EXPECT_EQ(0x64d09d4fd8U, unwinder.frames()[0].pc);
245 EXPECT_EQ(0x7fe0d84040U, unwinder.frames()[0].sp);
246 EXPECT_EQ(0x64d09d5078U, unwinder.frames()[1].pc);
247 EXPECT_EQ(0x7fe0d84070U, unwinder.frames()[1].sp);
248 EXPECT_EQ(0x64d09d508cU, unwinder.frames()[2].pc);
249 EXPECT_EQ(0x7fe0d84080U, unwinder.frames()[2].sp);
250 EXPECT_EQ(0x64d09d88fcU, unwinder.frames()[3].pc);
251 EXPECT_EQ(0x7fe0d84090U, unwinder.frames()[3].sp);
252 EXPECT_EQ(0x64d09d88d8U, unwinder.frames()[4].pc);
253 EXPECT_EQ(0x7fe0d840f0U, unwinder.frames()[4].sp);
254 EXPECT_EQ(0x64d0a00d70U, unwinder.frames()[5].pc);
255 EXPECT_EQ(0x7fe0d84110U, unwinder.frames()[5].sp);
232} 256}
233 257
234static void AddMemory(std::string file_name, MemoryOfflineParts* parts) { 258static void AddMemory(std::string file_name, MemoryOfflineParts* parts) {
@@ -390,6 +414,144 @@ TEST_F(UnwindOfflineTest, jit_debug_x86) {
390 " #67 pc 00001a80 dalvikvm32 (main+1312)\n" 414 " #67 pc 00001a80 dalvikvm32 (main+1312)\n"
391 " #68 pc 00018275 libc.so\n", 415 " #68 pc 00018275 libc.so\n",
392 frame_info); 416 frame_info);
417 EXPECT_EQ(0xeb89bfb8U, unwinder.frames()[0].pc);
418 EXPECT_EQ(0xffeb5280U, unwinder.frames()[0].sp);
419 EXPECT_EQ(0xeb89af00U, unwinder.frames()[1].pc);
420 EXPECT_EQ(0xffeb52a0U, unwinder.frames()[1].sp);
421 EXPECT_EQ(0xec6061a8U, unwinder.frames()[2].pc);
422 EXPECT_EQ(0xffeb5ce0U, unwinder.frames()[2].sp);
423 EXPECT_EQ(0xee75be81U, unwinder.frames()[3].pc);
424 EXPECT_EQ(0xffeb5d30U, unwinder.frames()[3].sp);
425 EXPECT_EQ(0xf728e4d2U, unwinder.frames()[4].pc);
426 EXPECT_EQ(0xffeb5d60U, unwinder.frames()[4].sp);
427 EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[5].pc);
428 EXPECT_EQ(0xffeb5d80U, unwinder.frames()[5].sp);
429 EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[6].pc);
430 EXPECT_EQ(0xffeb5e20U, unwinder.frames()[6].sp);
431 EXPECT_EQ(0xf6f73552U, unwinder.frames()[7].pc);
432 EXPECT_EQ(0xffeb5ec0U, unwinder.frames()[7].sp);
433 EXPECT_EQ(0xf6f7499aU, unwinder.frames()[8].pc);
434 EXPECT_EQ(0xffeb5f40U, unwinder.frames()[8].sp);
435 EXPECT_EQ(0xf7265362U, unwinder.frames()[9].pc);
436 EXPECT_EQ(0xffeb5fb0U, unwinder.frames()[9].sp);
437 EXPECT_EQ(0xf72945bdU, unwinder.frames()[10].pc);
438 EXPECT_EQ(0xffeb6110U, unwinder.frames()[10].sp);
439 EXPECT_EQ(0xee75be04U, unwinder.frames()[11].pc);
440 EXPECT_EQ(0xffeb6160U, unwinder.frames()[11].sp);
441 EXPECT_EQ(0xf728e4d2U, unwinder.frames()[12].pc);
442 EXPECT_EQ(0xffeb6180U, unwinder.frames()[12].sp);
443 EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[13].pc);
444 EXPECT_EQ(0xffeb61b0U, unwinder.frames()[13].sp);
445 EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[14].pc);
446 EXPECT_EQ(0xffeb6250U, unwinder.frames()[14].sp);
447 EXPECT_EQ(0xf6f73552U, unwinder.frames()[15].pc);
448 EXPECT_EQ(0xffeb62f0U, unwinder.frames()[15].sp);
449 EXPECT_EQ(0xf6f7499aU, unwinder.frames()[16].pc);
450 EXPECT_EQ(0xffeb6370U, unwinder.frames()[16].sp);
451 EXPECT_EQ(0xf7265362U, unwinder.frames()[17].pc);
452 EXPECT_EQ(0xffeb63e0U, unwinder.frames()[17].sp);
453 EXPECT_EQ(0xf72945bdU, unwinder.frames()[18].pc);
454 EXPECT_EQ(0xffeb6530U, unwinder.frames()[18].sp);
455 EXPECT_EQ(0xee75bd3cU, unwinder.frames()[19].pc);
456 EXPECT_EQ(0xffeb6580U, unwinder.frames()[19].sp);
457 EXPECT_EQ(0xf728e4d2U, unwinder.frames()[20].pc);
458 EXPECT_EQ(0xffeb65b0U, unwinder.frames()[20].sp);
459 EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[21].pc);
460 EXPECT_EQ(0xffeb65e0U, unwinder.frames()[21].sp);
461 EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[22].pc);
462 EXPECT_EQ(0xffeb6680U, unwinder.frames()[22].sp);
463 EXPECT_EQ(0xf6f73552U, unwinder.frames()[23].pc);
464 EXPECT_EQ(0xffeb6720U, unwinder.frames()[23].sp);
465 EXPECT_EQ(0xf6f7499aU, unwinder.frames()[24].pc);
466 EXPECT_EQ(0xffeb67a0U, unwinder.frames()[24].sp);
467 EXPECT_EQ(0xf7265362U, unwinder.frames()[25].pc);
468 EXPECT_EQ(0xffeb6810U, unwinder.frames()[25].sp);
469 EXPECT_EQ(0xf72945bdU, unwinder.frames()[26].pc);
470 EXPECT_EQ(0xffeb6960U, unwinder.frames()[26].sp);
471 EXPECT_EQ(0xee75bbdcU, unwinder.frames()[27].pc);
472 EXPECT_EQ(0xffeb69b0U, unwinder.frames()[27].sp);
473 EXPECT_EQ(0xf728e6a2U, unwinder.frames()[28].pc);
474 EXPECT_EQ(0xffeb69f0U, unwinder.frames()[28].sp);
475 EXPECT_EQ(0xf6d27acbU, unwinder.frames()[29].pc);
476 EXPECT_EQ(0xffeb6a20U, unwinder.frames()[29].sp);
477 EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[30].pc);
478 EXPECT_EQ(0xffeb6ac0U, unwinder.frames()[30].sp);
479 EXPECT_EQ(0xf6f73552U, unwinder.frames()[31].pc);
480 EXPECT_EQ(0xffeb6b60U, unwinder.frames()[31].sp);
481 EXPECT_EQ(0xf6f7499aU, unwinder.frames()[32].pc);
482 EXPECT_EQ(0xffeb6be0U, unwinder.frames()[32].sp);
483 EXPECT_EQ(0xf7265362U, unwinder.frames()[33].pc);
484 EXPECT_EQ(0xffeb6c50U, unwinder.frames()[33].sp);
485 EXPECT_EQ(0xf72945bdU, unwinder.frames()[34].pc);
486 EXPECT_EQ(0xffeb6dd0U, unwinder.frames()[34].sp);
487 EXPECT_EQ(0xee75b625U, unwinder.frames()[35].pc);
488 EXPECT_EQ(0xffeb6e20U, unwinder.frames()[35].sp);
489 EXPECT_EQ(0xf728e4d2U, unwinder.frames()[36].pc);
490 EXPECT_EQ(0xffeb6e50U, unwinder.frames()[36].sp);
491 EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[37].pc);
492 EXPECT_EQ(0xffeb6e70U, unwinder.frames()[37].sp);
493 EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[38].pc);
494 EXPECT_EQ(0xffeb6f10U, unwinder.frames()[38].sp);
495 EXPECT_EQ(0xf6f73552U, unwinder.frames()[39].pc);
496 EXPECT_EQ(0xffeb6fb0U, unwinder.frames()[39].sp);
497 EXPECT_EQ(0xf6f7499aU, unwinder.frames()[40].pc);
498 EXPECT_EQ(0xffeb7030U, unwinder.frames()[40].sp);
499 EXPECT_EQ(0xf7265362U, unwinder.frames()[41].pc);
500 EXPECT_EQ(0xffeb70a0U, unwinder.frames()[41].sp);
501 EXPECT_EQ(0xf72945bdU, unwinder.frames()[42].pc);
502 EXPECT_EQ(0xffeb71f0U, unwinder.frames()[42].sp);
503 EXPECT_EQ(0xee75aedcU, unwinder.frames()[43].pc);
504 EXPECT_EQ(0xffeb7240U, unwinder.frames()[43].sp);
505 EXPECT_EQ(0xf728e4d2U, unwinder.frames()[44].pc);
506 EXPECT_EQ(0xffeb72a0U, unwinder.frames()[44].sp);
507 EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[45].pc);
508 EXPECT_EQ(0xffeb72c0U, unwinder.frames()[45].sp);
509 EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[46].pc);
510 EXPECT_EQ(0xffeb7360U, unwinder.frames()[46].sp);
511 EXPECT_EQ(0xf6f73552U, unwinder.frames()[47].pc);
512 EXPECT_EQ(0xffeb7400U, unwinder.frames()[47].sp);
513 EXPECT_EQ(0xf6f7499aU, unwinder.frames()[48].pc);
514 EXPECT_EQ(0xffeb7480U, unwinder.frames()[48].sp);
515 EXPECT_EQ(0xf7265362U, unwinder.frames()[49].pc);
516 EXPECT_EQ(0xffeb74f0U, unwinder.frames()[49].sp);
517 EXPECT_EQ(0xf72945bdU, unwinder.frames()[50].pc);
518 EXPECT_EQ(0xffeb7680U, unwinder.frames()[50].sp);
519 EXPECT_EQ(0xee756c22U, unwinder.frames()[51].pc);
520 EXPECT_EQ(0xffeb76d0U, unwinder.frames()[51].sp);
521 EXPECT_EQ(0xf728e6a2U, unwinder.frames()[52].pc);
522 EXPECT_EQ(0xffeb76f0U, unwinder.frames()[52].sp);
523 EXPECT_EQ(0xf6d27acbU, unwinder.frames()[53].pc);
524 EXPECT_EQ(0xffeb7710U, unwinder.frames()[53].sp);
525 EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[54].pc);
526 EXPECT_EQ(0xffeb77b0U, unwinder.frames()[54].sp);
527 EXPECT_EQ(0xf6f73552U, unwinder.frames()[55].pc);
528 EXPECT_EQ(0xffeb7850U, unwinder.frames()[55].sp);
529 EXPECT_EQ(0xf6f7499aU, unwinder.frames()[56].pc);
530 EXPECT_EQ(0xffeb78d0U, unwinder.frames()[56].sp);
531 EXPECT_EQ(0xf7265362U, unwinder.frames()[57].pc);
532 EXPECT_EQ(0xffeb7940U, unwinder.frames()[57].sp);
533 EXPECT_EQ(0xf72945bdU, unwinder.frames()[58].pc);
534 EXPECT_EQ(0xffeb7a80U, unwinder.frames()[58].sp);
535 EXPECT_EQ(0xf728e6a2U, unwinder.frames()[59].pc);
536 EXPECT_EQ(0xffeb7ad0U, unwinder.frames()[59].sp);
537 EXPECT_EQ(0xf6d27acbU, unwinder.frames()[60].pc);
538 EXPECT_EQ(0xffeb7af0U, unwinder.frames()[60].sp);
539 EXPECT_EQ(0xf718bc95U, unwinder.frames()[61].pc);
540 EXPECT_EQ(0xffeb7b90U, unwinder.frames()[61].sp);
541 EXPECT_EQ(0xf718bb5aU, unwinder.frames()[62].pc);
542 EXPECT_EQ(0xffeb7c50U, unwinder.frames()[62].sp);
543 EXPECT_EQ(0xf706b3ddU, unwinder.frames()[63].pc);
544 EXPECT_EQ(0xffeb7d10U, unwinder.frames()[63].sp);
545 EXPECT_EQ(0xf6d6548cU, unwinder.frames()[64].pc);
546 EXPECT_EQ(0xffeb7d70U, unwinder.frames()[64].sp);
547 EXPECT_EQ(0xf6d5df06U, unwinder.frames()[65].pc);
548 EXPECT_EQ(0xffeb7df0U, unwinder.frames()[65].sp);
549 EXPECT_EQ(0x56574d8cU, unwinder.frames()[66].pc);
550 EXPECT_EQ(0xffeb7e40U, unwinder.frames()[66].sp);
551 EXPECT_EQ(0x56574a80U, unwinder.frames()[67].pc);
552 EXPECT_EQ(0xffeb7e70U, unwinder.frames()[67].sp);
553 EXPECT_EQ(0xf7363275U, unwinder.frames()[68].pc);
554 EXPECT_EQ(0xffeb7ef0U, unwinder.frames()[68].sp);
393} 555}
394 556
395TEST_F(UnwindOfflineTest, jit_debug_arm) { 557TEST_F(UnwindOfflineTest, jit_debug_arm) {
@@ -553,6 +715,158 @@ TEST_F(UnwindOfflineTest, jit_debug_arm) {
553 " #74 pc 00001349 dalvikvm32 (main+896)\n" 715 " #74 pc 00001349 dalvikvm32 (main+896)\n"
554 " #75 pc 000850c9 libc.so\n", 716 " #75 pc 000850c9 libc.so\n",
555 frame_info); 717 frame_info);
718 EXPECT_EQ(0xdfe66a5eU, unwinder.frames()[0].pc);
719 EXPECT_EQ(0xff85d180U, unwinder.frames()[0].sp);
720 EXPECT_EQ(0xe044712dU, unwinder.frames()[1].pc);
721 EXPECT_EQ(0xff85d200U, unwinder.frames()[1].sp);
722 EXPECT_EQ(0xe27a7cb1U, unwinder.frames()[2].pc);
723 EXPECT_EQ(0xff85d290U, unwinder.frames()[2].sp);
724 EXPECT_EQ(0xed75c175U, unwinder.frames()[3].pc);
725 EXPECT_EQ(0xff85d2b0U, unwinder.frames()[3].sp);
726 EXPECT_EQ(0xed761129U, unwinder.frames()[4].pc);
727 EXPECT_EQ(0xff85d2e8U, unwinder.frames()[4].sp);
728 EXPECT_EQ(0xed3b97a9U, unwinder.frames()[5].pc);
729 EXPECT_EQ(0xff85d370U, unwinder.frames()[5].sp);
730 EXPECT_EQ(0xed541833U, unwinder.frames()[6].pc);
731 EXPECT_EQ(0xff85d3d8U, unwinder.frames()[6].sp);
732 EXPECT_EQ(0xed528935U, unwinder.frames()[7].pc);
733 EXPECT_EQ(0xff85d428U, unwinder.frames()[7].sp);
734 EXPECT_EQ(0xed52971dU, unwinder.frames()[8].pc);
735 EXPECT_EQ(0xff85d470U, unwinder.frames()[8].sp);
736 EXPECT_EQ(0xed73c865U, unwinder.frames()[9].pc);
737 EXPECT_EQ(0xff85d4b0U, unwinder.frames()[9].sp);
738 EXPECT_EQ(0xed7606ffU, unwinder.frames()[10].pc);
739 EXPECT_EQ(0xff85d5d0U, unwinder.frames()[10].sp);
740 EXPECT_EQ(0xe27a7c31U, unwinder.frames()[11].pc);
741 EXPECT_EQ(0xff85d640U, unwinder.frames()[11].sp);
742 EXPECT_EQ(0xed75c175U, unwinder.frames()[12].pc);
743 EXPECT_EQ(0xff85d660U, unwinder.frames()[12].sp);
744 EXPECT_EQ(0xed761129U, unwinder.frames()[13].pc);
745 EXPECT_EQ(0xff85d698U, unwinder.frames()[13].sp);
746 EXPECT_EQ(0xed3b97a9U, unwinder.frames()[14].pc);
747 EXPECT_EQ(0xff85d720U, unwinder.frames()[14].sp);
748 EXPECT_EQ(0xed541833U, unwinder.frames()[15].pc);
749 EXPECT_EQ(0xff85d788U, unwinder.frames()[15].sp);
750 EXPECT_EQ(0xed528935U, unwinder.frames()[16].pc);
751 EXPECT_EQ(0xff85d7d8U, unwinder.frames()[16].sp);
752 EXPECT_EQ(0xed52971dU, unwinder.frames()[17].pc);
753 EXPECT_EQ(0xff85d820U, unwinder.frames()[17].sp);
754 EXPECT_EQ(0xed73c865U, unwinder.frames()[18].pc);
755 EXPECT_EQ(0xff85d860U, unwinder.frames()[18].sp);
756 EXPECT_EQ(0xed7606ffU, unwinder.frames()[19].pc);
757 EXPECT_EQ(0xff85d970U, unwinder.frames()[19].sp);
758 EXPECT_EQ(0xe27a7b77U, unwinder.frames()[20].pc);
759 EXPECT_EQ(0xff85d9e0U, unwinder.frames()[20].sp);
760 EXPECT_EQ(0xed75c175U, unwinder.frames()[21].pc);
761 EXPECT_EQ(0xff85da10U, unwinder.frames()[21].sp);
762 EXPECT_EQ(0xed761129U, unwinder.frames()[22].pc);
763 EXPECT_EQ(0xff85da48U, unwinder.frames()[22].sp);
764 EXPECT_EQ(0xed3b97a9U, unwinder.frames()[23].pc);
765 EXPECT_EQ(0xff85dad0U, unwinder.frames()[23].sp);
766 EXPECT_EQ(0xed541833U, unwinder.frames()[24].pc);
767 EXPECT_EQ(0xff85db38U, unwinder.frames()[24].sp);
768 EXPECT_EQ(0xed528935U, unwinder.frames()[25].pc);
769 EXPECT_EQ(0xff85db88U, unwinder.frames()[25].sp);
770 EXPECT_EQ(0xed52971dU, unwinder.frames()[26].pc);
771 EXPECT_EQ(0xff85dbd0U, unwinder.frames()[26].sp);
772 EXPECT_EQ(0xed73c865U, unwinder.frames()[27].pc);
773 EXPECT_EQ(0xff85dc10U, unwinder.frames()[27].sp);
774 EXPECT_EQ(0xed7606ffU, unwinder.frames()[28].pc);
775 EXPECT_EQ(0xff85dd20U, unwinder.frames()[28].sp);
776 EXPECT_EQ(0xe27a7a29U, unwinder.frames()[29].pc);
777 EXPECT_EQ(0xff85dd90U, unwinder.frames()[29].sp);
778 EXPECT_EQ(0xed75c175U, unwinder.frames()[30].pc);
779 EXPECT_EQ(0xff85ddc0U, unwinder.frames()[30].sp);
780 EXPECT_EQ(0xed76122fU, unwinder.frames()[31].pc);
781 EXPECT_EQ(0xff85de08U, unwinder.frames()[31].sp);
782 EXPECT_EQ(0xed3b97bbU, unwinder.frames()[32].pc);
783 EXPECT_EQ(0xff85de90U, unwinder.frames()[32].sp);
784 EXPECT_EQ(0xed541833U, unwinder.frames()[33].pc);
785 EXPECT_EQ(0xff85def8U, unwinder.frames()[33].sp);
786 EXPECT_EQ(0xed528935U, unwinder.frames()[34].pc);
787 EXPECT_EQ(0xff85df48U, unwinder.frames()[34].sp);
788 EXPECT_EQ(0xed52971dU, unwinder.frames()[35].pc);
789 EXPECT_EQ(0xff85df90U, unwinder.frames()[35].sp);
790 EXPECT_EQ(0xed73c865U, unwinder.frames()[36].pc);
791 EXPECT_EQ(0xff85dfd0U, unwinder.frames()[36].sp);
792 EXPECT_EQ(0xed7606ffU, unwinder.frames()[37].pc);
793 EXPECT_EQ(0xff85e110U, unwinder.frames()[37].sp);
794 EXPECT_EQ(0xe27a739bU, unwinder.frames()[38].pc);
795 EXPECT_EQ(0xff85e180U, unwinder.frames()[38].sp);
796 EXPECT_EQ(0xed75c175U, unwinder.frames()[39].pc);
797 EXPECT_EQ(0xff85e1b0U, unwinder.frames()[39].sp);
798 EXPECT_EQ(0xed761129U, unwinder.frames()[40].pc);
799 EXPECT_EQ(0xff85e1e0U, unwinder.frames()[40].sp);
800 EXPECT_EQ(0xed3b97a9U, unwinder.frames()[41].pc);
801 EXPECT_EQ(0xff85e268U, unwinder.frames()[41].sp);
802 EXPECT_EQ(0xed541833U, unwinder.frames()[42].pc);
803 EXPECT_EQ(0xff85e2d0U, unwinder.frames()[42].sp);
804 EXPECT_EQ(0xed528935U, unwinder.frames()[43].pc);
805 EXPECT_EQ(0xff85e320U, unwinder.frames()[43].sp);
806 EXPECT_EQ(0xed52971dU, unwinder.frames()[44].pc);
807 EXPECT_EQ(0xff85e368U, unwinder.frames()[44].sp);
808 EXPECT_EQ(0xed73c865U, unwinder.frames()[45].pc);
809 EXPECT_EQ(0xff85e3a8U, unwinder.frames()[45].sp);
810 EXPECT_EQ(0xed7606ffU, unwinder.frames()[46].pc);
811 EXPECT_EQ(0xff85e4c0U, unwinder.frames()[46].sp);
812 EXPECT_EQ(0xe27a6aa7U, unwinder.frames()[47].pc);
813 EXPECT_EQ(0xff85e530U, unwinder.frames()[47].sp);
814 EXPECT_EQ(0xed75c175U, unwinder.frames()[48].pc);
815 EXPECT_EQ(0xff85e5a0U, unwinder.frames()[48].sp);
816 EXPECT_EQ(0xed761129U, unwinder.frames()[49].pc);
817 EXPECT_EQ(0xff85e5d8U, unwinder.frames()[49].sp);
818 EXPECT_EQ(0xed3b97a9U, unwinder.frames()[50].pc);
819 EXPECT_EQ(0xff85e660U, unwinder.frames()[50].sp);
820 EXPECT_EQ(0xed541833U, unwinder.frames()[51].pc);
821 EXPECT_EQ(0xff85e6c8U, unwinder.frames()[51].sp);
822 EXPECT_EQ(0xed528935U, unwinder.frames()[52].pc);
823 EXPECT_EQ(0xff85e718U, unwinder.frames()[52].sp);
824 EXPECT_EQ(0xed52971dU, unwinder.frames()[53].pc);
825 EXPECT_EQ(0xff85e760U, unwinder.frames()[53].sp);
826 EXPECT_EQ(0xed73c865U, unwinder.frames()[54].pc);
827 EXPECT_EQ(0xff85e7a0U, unwinder.frames()[54].sp);
828 EXPECT_EQ(0xed7606ffU, unwinder.frames()[55].pc);
829 EXPECT_EQ(0xff85e8f0U, unwinder.frames()[55].sp);
830 EXPECT_EQ(0xe27a1a99U, unwinder.frames()[56].pc);
831 EXPECT_EQ(0xff85e960U, unwinder.frames()[56].sp);
832 EXPECT_EQ(0xed75c175U, unwinder.frames()[57].pc);
833 EXPECT_EQ(0xff85e990U, unwinder.frames()[57].sp);
834 EXPECT_EQ(0xed76122fU, unwinder.frames()[58].pc);
835 EXPECT_EQ(0xff85e9c8U, unwinder.frames()[58].sp);
836 EXPECT_EQ(0xed3b97bbU, unwinder.frames()[59].pc);
837 EXPECT_EQ(0xff85ea50U, unwinder.frames()[59].sp);
838 EXPECT_EQ(0xed541833U, unwinder.frames()[60].pc);
839 EXPECT_EQ(0xff85eab8U, unwinder.frames()[60].sp);
840 EXPECT_EQ(0xed528935U, unwinder.frames()[61].pc);
841 EXPECT_EQ(0xff85eb08U, unwinder.frames()[61].sp);
842 EXPECT_EQ(0xed52971dU, unwinder.frames()[62].pc);
843 EXPECT_EQ(0xff85eb50U, unwinder.frames()[62].sp);
844 EXPECT_EQ(0xed73c865U, unwinder.frames()[63].pc);
845 EXPECT_EQ(0xff85eb90U, unwinder.frames()[63].sp);
846 EXPECT_EQ(0xed7606ffU, unwinder.frames()[64].pc);
847 EXPECT_EQ(0xff85ec90U, unwinder.frames()[64].sp);
848 EXPECT_EQ(0xed75c175U, unwinder.frames()[65].pc);
849 EXPECT_EQ(0xff85ed00U, unwinder.frames()[65].sp);
850 EXPECT_EQ(0xed76122fU, unwinder.frames()[66].pc);
851 EXPECT_EQ(0xff85ed38U, unwinder.frames()[66].sp);
852 EXPECT_EQ(0xed3b97bbU, unwinder.frames()[67].pc);
853 EXPECT_EQ(0xff85edc0U, unwinder.frames()[67].sp);
854 EXPECT_EQ(0xed6ac92dU, unwinder.frames()[68].pc);
855 EXPECT_EQ(0xff85ee28U, unwinder.frames()[68].sp);
856 EXPECT_EQ(0xed6ac6c3U, unwinder.frames()[69].pc);
857 EXPECT_EQ(0xff85eeb8U, unwinder.frames()[69].sp);
858 EXPECT_EQ(0xed602411U, unwinder.frames()[70].pc);
859 EXPECT_EQ(0xff85ef48U, unwinder.frames()[70].sp);
860 EXPECT_EQ(0xed3e0a9fU, unwinder.frames()[71].pc);
861 EXPECT_EQ(0xff85ef90U, unwinder.frames()[71].sp);
862 EXPECT_EQ(0xed3db9b9U, unwinder.frames()[72].pc);
863 EXPECT_EQ(0xff85f008U, unwinder.frames()[72].sp);
864 EXPECT_EQ(0xab0d459fU, unwinder.frames()[73].pc);
865 EXPECT_EQ(0xff85f038U, unwinder.frames()[73].sp);
866 EXPECT_EQ(0xab0d4349U, unwinder.frames()[74].pc);
867 EXPECT_EQ(0xff85f050U, unwinder.frames()[74].sp);
868 EXPECT_EQ(0xedb0d0c9U, unwinder.frames()[75].pc);
869 EXPECT_EQ(0xff85f0c0U, unwinder.frames()[75].sp);
556} 870}
557 871
558// The eh_frame_hdr data is present but set to zero fdes. This should 872// The eh_frame_hdr data is present but set to zero fdes. This should
@@ -573,6 +887,16 @@ TEST_F(UnwindOfflineTest, bad_eh_frame_hdr_arm64) {
573 " #03 pc 0000000000000590 waiter64\n" 887 " #03 pc 0000000000000590 waiter64\n"
574 " #04 pc 00000000000a8e98 libc.so (__libc_init+88)\n", 888 " #04 pc 00000000000a8e98 libc.so (__libc_init+88)\n",
575 frame_info); 889 frame_info);
890 EXPECT_EQ(0x60a9fdf550U, unwinder.frames()[0].pc);
891 EXPECT_EQ(0x7fdd141990U, unwinder.frames()[0].sp);
892 EXPECT_EQ(0x60a9fdf568U, unwinder.frames()[1].pc);
893 EXPECT_EQ(0x7fdd1419a0U, unwinder.frames()[1].sp);
894 EXPECT_EQ(0x60a9fdf57cU, unwinder.frames()[2].pc);
895 EXPECT_EQ(0x7fdd1419b0U, unwinder.frames()[2].sp);
896 EXPECT_EQ(0x60a9fdf590U, unwinder.frames()[3].pc);
897 EXPECT_EQ(0x7fdd1419c0U, unwinder.frames()[3].sp);
898 EXPECT_EQ(0x7542d68e98U, unwinder.frames()[4].pc);
899 EXPECT_EQ(0x7fdd1419d0U, unwinder.frames()[4].sp);
576} 900}
577 901
578// The elf has bad eh_frame unwind information for the pcs. If eh_frame 902// The elf has bad eh_frame unwind information for the pcs. If eh_frame
@@ -592,6 +916,16 @@ TEST_F(UnwindOfflineTest, debug_frame_first_x86) {
592 " #03 pc 000006f7 waiter (main+23)\n" 916 " #03 pc 000006f7 waiter (main+23)\n"
593 " #04 pc 00018275 libc.so\n", 917 " #04 pc 00018275 libc.so\n",
594 frame_info); 918 frame_info);
919 EXPECT_EQ(0x56598685U, unwinder.frames()[0].pc);
920 EXPECT_EQ(0xffcf9e38U, unwinder.frames()[0].sp);
921 EXPECT_EQ(0x565986b7U, unwinder.frames()[1].pc);
922 EXPECT_EQ(0xffcf9e50U, unwinder.frames()[1].sp);
923 EXPECT_EQ(0x565986d7U, unwinder.frames()[2].pc);
924 EXPECT_EQ(0xffcf9e60U, unwinder.frames()[2].sp);
925 EXPECT_EQ(0x565986f7U, unwinder.frames()[3].pc);
926 EXPECT_EQ(0xffcf9e70U, unwinder.frames()[3].sp);
927 EXPECT_EQ(0xf744a275U, unwinder.frames()[4].pc);
928 EXPECT_EQ(0xffcf9e80U, unwinder.frames()[4].sp);
595} 929}
596 930
597// Make sure that a pc that is at the beginning of an fde unwinds correctly. 931// Make sure that a pc that is at the beginning of an fde unwinds correctly.
@@ -610,6 +944,16 @@ TEST_F(UnwindOfflineTest, eh_frame_hdr_begin_x86_64) {
610 " #03 pc 00000000000013ed unwind_test64 (main+13)\n" 944 " #03 pc 00000000000013ed unwind_test64 (main+13)\n"
611 " #04 pc 00000000000202b0 libc.so\n", 945 " #04 pc 00000000000202b0 libc.so\n",
612 frame_info); 946 frame_info);
947 EXPECT_EQ(0x561550b17a80U, unwinder.frames()[0].pc);
948 EXPECT_EQ(0x7ffcc8596ce8U, unwinder.frames()[0].sp);
949 EXPECT_EQ(0x561550b17dd9U, unwinder.frames()[1].pc);
950 EXPECT_EQ(0x7ffcc8596cf0U, unwinder.frames()[1].sp);
951 EXPECT_EQ(0x561550b1821eU, unwinder.frames()[2].pc);
952 EXPECT_EQ(0x7ffcc8596f40U, unwinder.frames()[2].sp);
953 EXPECT_EQ(0x561550b183edU, unwinder.frames()[3].pc);
954 EXPECT_EQ(0x7ffcc8597190U, unwinder.frames()[3].sp);
955 EXPECT_EQ(0x7f4de62162b0U, unwinder.frames()[4].pc);
956 EXPECT_EQ(0x7ffcc85971a0U, unwinder.frames()[4].sp);
613} 957}
614 958
615} // namespace unwindstack 959} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 7fbae4cf8..e44b225c5 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -196,6 +196,67 @@ TEST_F(UnwinderTest, multiple_frames) {
196 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); 196 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
197} 197}
198 198
199TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) {
200 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
201 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
202 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
203
204 regs_.FakeSetPc(0x1000);
205 regs_.FakeSetSp(0x10000);
206 ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
207 ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
208 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
209
210 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
211 unwinder.SetResolveNames(false);
212 unwinder.Unwind();
213 EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
214
215 ASSERT_EQ(3U, unwinder.NumFrames());
216
217 auto* frame = &unwinder.frames()[0];
218 EXPECT_EQ(0U, frame->num);
219 EXPECT_EQ(0U, frame->rel_pc);
220 EXPECT_EQ(0x1000U, frame->pc);
221 EXPECT_EQ(0x10000U, frame->sp);
222 EXPECT_EQ("", frame->function_name);
223 EXPECT_EQ(0U, frame->function_offset);
224 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
225 EXPECT_EQ(0U, frame->map_offset);
226 EXPECT_EQ(0x1000U, frame->map_start);
227 EXPECT_EQ(0x8000U, frame->map_end);
228 EXPECT_EQ(0U, frame->map_load_bias);
229 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
230
231 frame = &unwinder.frames()[1];
232 EXPECT_EQ(1U, frame->num);
233 EXPECT_EQ(0x100U, frame->rel_pc);
234 EXPECT_EQ(0x1100U, frame->pc);
235 EXPECT_EQ(0x10010U, frame->sp);
236 EXPECT_EQ("", frame->function_name);
237 EXPECT_EQ(0U, frame->function_offset);
238 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
239 EXPECT_EQ(0U, frame->map_offset);
240 EXPECT_EQ(0x1000U, frame->map_start);
241 EXPECT_EQ(0x8000U, frame->map_end);
242 EXPECT_EQ(0U, frame->map_load_bias);
243 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
244
245 frame = &unwinder.frames()[2];
246 EXPECT_EQ(2U, frame->num);
247 EXPECT_EQ(0x200U, frame->rel_pc);
248 EXPECT_EQ(0x1200U, frame->pc);
249 EXPECT_EQ(0x10020U, frame->sp);
250 EXPECT_EQ("", frame->function_name);
251 EXPECT_EQ(0U, frame->function_offset);
252 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
253 EXPECT_EQ(0U, frame->map_offset);
254 EXPECT_EQ(0x1000U, frame->map_start);
255 EXPECT_EQ(0x8000U, frame->map_end);
256 EXPECT_EQ(0U, frame->map_load_bias);
257 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
258}
259
199TEST_F(UnwinderTest, non_zero_load_bias) { 260TEST_F(UnwinderTest, non_zero_load_bias) {
200 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); 261 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
201 262
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 7f2d11d67..a0abccae2 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -120,6 +120,11 @@ int GetElfInfo(const char* file, uint64_t offset) {
120 return 1; 120 return 1;
121 } 121 }
122 122
123 std::string soname;
124 if (elf.GetSoname(&soname)) {
125 printf("Soname: %s\n", soname.c_str());
126 }
127
123 ElfInterface* interface = elf.interface(); 128 ElfInterface* interface = elf.interface();
124 if (elf.machine_type() == EM_ARM) { 129 if (elf.machine_type() == EM_ARM) {
125 DumpArm(reinterpret_cast<ElfInterfaceArm*>(interface)); 130 DumpArm(reinterpret_cast<ElfInterfaceArm*>(interface));
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
index 4d890879f..47a4f912d 100644
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ b/libunwindstack/tools/unwind_reg_info.cpp
@@ -157,6 +157,11 @@ int GetInfo(const char* file, uint64_t pc) {
157 return 1; 157 return 1;
158 } 158 }
159 159
160 std::string soname;
161 if (elf.GetSoname(&soname)) {
162 printf("Soname: %s\n\n", soname.c_str());
163 }
164
160 printf("PC 0x%" PRIx64 ":\n", pc); 165 printf("PC 0x%" PRIx64 ":\n", pc);
161 166
162 DwarfSection* section = interface->eh_frame(); 167 DwarfSection* section = interface->eh_frame();
diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp
index 697e4cd9e..086dffef3 100644
--- a/libunwindstack/tools/unwind_symbols.cpp
+++ b/libunwindstack/tools/unwind_symbols.cpp
@@ -71,6 +71,11 @@ int main(int argc, char** argv) {
71 return 1; 71 return 1;
72 } 72 }
73 73
74 std::string soname;
75 if (elf.GetSoname(&soname)) {
76 printf("Soname: %s\n\n", soname.c_str());
77 }
78
74 switch (elf.machine_type()) { 79 switch (elf.machine_type()) {
75 case EM_ARM: 80 case EM_ARM:
76 printf("ABI: arm\n"); 81 printf("ABI: arm\n");
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 2be5d9896..80dcdcbe9 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -20,12 +20,12 @@ cc_library_headers {
20 header_libs: [ 20 header_libs: [
21 "liblog_headers", 21 "liblog_headers",
22 "libsystem_headers", 22 "libsystem_headers",
23 "libcutils_headers" 23 "libcutils_headers",
24 ], 24 ],
25 export_header_lib_headers: [ 25 export_header_lib_headers: [
26 "liblog_headers", 26 "liblog_headers",
27 "libsystem_headers", 27 "libsystem_headers",
28 "libcutils_headers" 28 "libcutils_headers",
29 ], 29 ],
30 export_include_dirs: ["include"], 30 export_include_dirs: ["include"],
31 31
@@ -52,7 +52,10 @@ cc_defaults {
52 }, 52 },
53 host_supported: true, 53 host_supported: true,
54 54
55 cflags: ["-Wall", "-Werror"], 55 cflags: [
56 "-Wall",
57 "-Werror",
58 ],
56 include_dirs: ["external/safe-iop/include"], 59 include_dirs: ["external/safe-iop/include"],
57 header_libs: [ 60 header_libs: [
58 "libutils_headers", 61 "libutils_headers",
@@ -193,7 +196,8 @@ cc_test {
193 static_libs: ["libutils"], 196 static_libs: ["libutils"],
194 shared_libs: ["liblog"], 197 shared_libs: ["liblog"],
195 srcs: ["SharedBufferTest.cpp"], 198 srcs: ["SharedBufferTest.cpp"],
196 cflags: ["-Wall", "-Werror"], 199 cflags: [
200 "-Wall",
201 "-Werror",
202 ],
197} 203}
198
199subdirs = ["tests"]
diff --git a/libutils/tests/Android.bp b/libutils/tests/Android.bp
index a3e7ffe73..1390552fa 100644
--- a/libutils/tests/Android.bp
+++ b/libutils/tests/Android.bp
@@ -77,7 +77,10 @@ cc_test_library {
77 host_supported: true, 77 host_supported: true,
78 relative_install_path: "libutils_tests", 78 relative_install_path: "libutils_tests",
79 srcs: ["Singleton_test1.cpp"], 79 srcs: ["Singleton_test1.cpp"],
80 cflags: ["-Wall", "-Werror"], 80 cflags: [
81 "-Wall",
82 "-Werror",
83 ],
81} 84}
82 85
83cc_test_library { 86cc_test_library {
@@ -85,6 +88,9 @@ cc_test_library {
85 host_supported: true, 88 host_supported: true,
86 relative_install_path: "libutils_tests", 89 relative_install_path: "libutils_tests",
87 srcs: ["Singleton_test2.cpp"], 90 srcs: ["Singleton_test2.cpp"],
88 cflags: ["-Wall", "-Werror"], 91 cflags: [
92 "-Wall",
93 "-Werror",
94 ],
89 shared_libs: ["libutils_tests_singleton1"], 95 shared_libs: ["libutils_tests_singleton1"],
90} 96}
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
index fec79b70d..e73b36652 100644
--- a/libvndksupport/Android.bp
+++ b/libvndksupport/Android.bp
@@ -3,7 +3,10 @@ subdirs = ["tests"]
3cc_library { 3cc_library {
4 name: "libvndksupport", 4 name: "libvndksupport",
5 srcs: ["linker.c"], 5 srcs: ["linker.c"],
6 cflags: ["-Wall", "-Werror"], 6 cflags: [
7 "-Wall",
8 "-Werror",
9 ],
7 local_include_dirs: ["include/vndksupport"], 10 local_include_dirs: ["include/vndksupport"],
8 export_include_dirs: ["include"], 11 export_include_dirs: ["include"],
9 shared_libs: ["liblog"], 12 shared_libs: ["liblog"],
diff --git a/libvndksupport/tests/Android.bp b/libvndksupport/tests/Android.bp
index 5b467f8ff..2570cce95 100644
--- a/libvndksupport/tests/Android.bp
+++ b/libvndksupport/tests/Android.bp
@@ -17,11 +17,14 @@ cc_test {
17 srcs: [ 17 srcs: [
18 "linker_test.cpp", 18 "linker_test.cpp",
19 ], 19 ],
20 cflags: ["-Wall", "-Werror"], 20 cflags: [
21 "-Wall",
22 "-Werror",
23 ],
21 24
22 host_supported: false, 25 host_supported: false,
23 shared_libs: [ 26 shared_libs: [
24 "libvndksupport", 27 "libvndksupport",
25 "libbase", 28 "libbase",
26 ] 29 ],
27} 30}
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index f9f8c73d9..5e5e7afd1 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -224,7 +224,9 @@ static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* arc
224 return kInvalidOffset; 224 return kInvalidOffset;
225 } 225 }
226 if (eocd->num_records == 0) { 226 if (eocd->num_records == 0) {
227#if defined(__ANDROID__)
227 ALOGW("Zip: empty archive?"); 228 ALOGW("Zip: empty archive?");
229#endif
228 return kEmptyArchive; 230 return kEmptyArchive;
229 } 231 }
230 232
diff --git a/lmkd/Android.bp b/lmkd/Android.bp
index 3f8a5035f..76d308a3c 100644
--- a/lmkd/Android.bp
+++ b/lmkd/Android.bp
@@ -4,10 +4,17 @@ cc_binary {
4 srcs: ["lmkd.c"], 4 srcs: ["lmkd.c"],
5 shared_libs: [ 5 shared_libs: [
6 "liblog", 6 "liblog",
7 "libprocessgroup",
8 "libcutils", 7 "libcutils",
9 ], 8 ],
10 cflags: ["-Werror"], 9 cflags: ["-Werror"],
11 10
12 init_rc: ["lmkd.rc"], 11 init_rc: ["lmkd.rc"],
12
13 product_variables: {
14 debuggable: {
15 cflags: [
16 "-DLMKD_TRACE_KILLS"
17 ],
18 },
19 },
13} 20}
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 15471e0cc..338e5fa20 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -29,13 +29,31 @@
29#include <sys/mman.h> 29#include <sys/mman.h>
30#include <sys/socket.h> 30#include <sys/socket.h>
31#include <sys/types.h> 31#include <sys/types.h>
32#include <time.h> 32#include <sys/sysinfo.h>
33#include <unistd.h> 33#include <unistd.h>
34 34
35#include <cutils/properties.h> 35#include <cutils/properties.h>
36#include <cutils/sockets.h> 36#include <cutils/sockets.h>
37#include <log/log.h> 37#include <log/log.h>
38#include <processgroup/processgroup.h> 38
39/*
40 * Define LMKD_TRACE_KILLS to record lmkd kills in kernel traces
41 * to profile and correlate with OOM kills
42 */
43#ifdef LMKD_TRACE_KILLS
44
45#define ATRACE_TAG ATRACE_TAG_ALWAYS
46#include <cutils/trace.h>
47
48#define TRACE_KILL_START(pid) ATRACE_INT(__FUNCTION__, pid);
49#define TRACE_KILL_END() ATRACE_INT(__FUNCTION__, 0);
50
51#else /* LMKD_TRACE_KILLS */
52
53#define TRACE_KILL_START(pid)
54#define TRACE_KILL_END()
55
56#endif /* LMKD_TRACE_KILLS */
39 57
40#ifndef __unused 58#ifndef __unused
41#define __unused __attribute__((__unused__)) 59#define __unused __attribute__((__unused__))
@@ -44,8 +62,6 @@
44#define MEMCG_SYSFS_PATH "/dev/memcg/" 62#define MEMCG_SYSFS_PATH "/dev/memcg/"
45#define MEMCG_MEMORY_USAGE "/dev/memcg/memory.usage_in_bytes" 63#define MEMCG_MEMORY_USAGE "/dev/memcg/memory.usage_in_bytes"
46#define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes" 64#define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes"
47#define MEMPRESSURE_WATCH_MEDIUM_LEVEL "medium"
48#define MEMPRESSURE_WATCH_CRITICAL_LEVEL "critical"
49#define ZONEINFO_PATH "/proc/zoneinfo" 65#define ZONEINFO_PATH "/proc/zoneinfo"
50#define LINE_MAX 128 66#define LINE_MAX 128
51 67
@@ -72,26 +88,47 @@ enum lmk_cmd {
72static int use_inkernel_interface = 1; 88static int use_inkernel_interface = 1;
73static bool has_inkernel_module; 89static bool has_inkernel_module;
74 90
75/* memory pressure level medium event */ 91/* memory pressure levels */
76static int mpevfd[2]; 92enum vmpressure_level {
77#define CRITICAL_INDEX 1 93 VMPRESS_LEVEL_LOW = 0,
78#define MEDIUM_INDEX 0 94 VMPRESS_LEVEL_MEDIUM,
95 VMPRESS_LEVEL_CRITICAL,
96 VMPRESS_LEVEL_COUNT
97};
98
99static const char *level_name[] = {
100 "low",
101 "medium",
102 "critical"
103};
79 104
80static int medium_oomadj; 105struct mem_size {
81static int critical_oomadj; 106 int free_mem;
107 int free_swap;
108};
109
110struct {
111 int min_free; /* recorded but not used yet */
112 int max_free;
113} low_pressure_mem = { -1, -1 };
114
115static int level_oomadj[VMPRESS_LEVEL_COUNT];
116static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 };
82static bool debug_process_killing; 117static bool debug_process_killing;
83static bool enable_pressure_upgrade; 118static bool enable_pressure_upgrade;
84static int64_t upgrade_pressure; 119static int64_t upgrade_pressure;
85static int64_t downgrade_pressure; 120static int64_t downgrade_pressure;
86static bool is_go_device; 121static bool is_go_device;
122static bool kill_heaviest_task;
123static unsigned long kill_timeout_ms;
87 124
88/* control socket listen and data */ 125/* control socket listen and data */
89static int ctrl_lfd; 126static int ctrl_lfd;
90static int ctrl_dfd = -1; 127static int ctrl_dfd = -1;
91static int ctrl_dfd_reopened; /* did we reopen ctrl conn on this loop? */ 128static int ctrl_dfd_reopened; /* did we reopen ctrl conn on this loop? */
92 129
93/* 2 memory pressure levels, 1 ctrl listen socket, 1 ctrl data socket */ 130/* 3 memory pressure levels, 1 ctrl listen socket, 1 ctrl data socket */
94#define MAX_EPOLL_EVENTS 4 131#define MAX_EPOLL_EVENTS 5
95static int epollfd; 132static int epollfd;
96static int maxevents; 133static int maxevents;
97 134
@@ -226,7 +263,7 @@ static int pid_remove(int pid) {
226 return 0; 263 return 0;
227} 264}
228 265
229static void writefilestring(char *path, char *s) { 266static void writefilestring(const char *path, char *s) {
230 int fd = open(path, O_WRONLY | O_CLOEXEC); 267 int fd = open(path, O_WRONLY | O_CLOEXEC);
231 int len = strlen(s); 268 int len = strlen(s);
232 int ret; 269 int ret;
@@ -534,6 +571,18 @@ static int zoneinfo_parse(struct sysmeminfo *mip) {
534 return 0; 571 return 0;
535} 572}
536 573
574static int get_free_memory(struct mem_size *ms) {
575 struct sysinfo si;
576
577 if (sysinfo(&si) < 0)
578 return -1;
579
580 ms->free_mem = (int)(si.freeram * si.mem_unit / PAGE_SIZE);
581 ms->free_swap = (int)(si.freeswap * si.mem_unit / PAGE_SIZE);
582
583 return 0;
584}
585
537static int proc_get_size(int pid) { 586static int proc_get_size(int pid) {
538 char path[PATH_MAX]; 587 char path[PATH_MAX];
539 char line[LINE_MAX]; 588 char line[LINE_MAX];
@@ -586,8 +635,32 @@ static struct proc *proc_adj_lru(int oomadj) {
586 return (struct proc *)adjslot_tail(&procadjslot_list[ADJTOSLOT(oomadj)]); 635 return (struct proc *)adjslot_tail(&procadjslot_list[ADJTOSLOT(oomadj)]);
587} 636}
588 637
638static struct proc *proc_get_heaviest(int oomadj) {
639 struct adjslot_list *head = &procadjslot_list[ADJTOSLOT(oomadj)];
640 struct adjslot_list *curr = head->next;
641 struct proc *maxprocp = NULL;
642 int maxsize = 0;
643 while (curr != head) {
644 int pid = ((struct proc *)curr)->pid;
645 int tasksize = proc_get_size(pid);
646 if (tasksize <= 0) {
647 struct adjslot_list *next = curr->next;
648 pid_remove(pid);
649 curr = next;
650 } else {
651 if (tasksize > maxsize) {
652 maxsize = tasksize;
653 maxprocp = (struct proc *)curr;
654 }
655 curr = curr->next;
656 }
657 }
658 return maxprocp;
659}
660
589/* Kill one process specified by procp. Returns the size of the process killed */ 661/* Kill one process specified by procp. Returns the size of the process killed */
590static int kill_one_process(struct proc* procp, int min_score_adj, bool is_critical) { 662static int kill_one_process(struct proc* procp, int min_score_adj,
663 enum vmpressure_level level) {
591 int pid = procp->pid; 664 int pid = procp->pid;
592 uid_t uid = procp->uid; 665 uid_t uid = procp->uid;
593 char *taskname; 666 char *taskname;
@@ -606,14 +679,18 @@ static int kill_one_process(struct proc* procp, int min_score_adj, bool is_criti
606 return -1; 679 return -1;
607 } 680 }
608 681
682 TRACE_KILL_START(pid);
683
684 r = kill(pid, SIGKILL);
609 ALOGI( 685 ALOGI(
610 "Killing '%s' (%d), uid %d, adj %d\n" 686 "Killing '%s' (%d), uid %d, adj %d\n"
611 " to free %ldkB because system is under %s memory pressure oom_adj %d\n", 687 " to free %ldkB because system is under %s memory pressure oom_adj %d\n",
612 taskname, pid, uid, procp->oomadj, tasksize * page_k, is_critical ? "critical" : "medium", 688 taskname, pid, uid, procp->oomadj, tasksize * page_k,
613 min_score_adj); 689 level_name[level], min_score_adj);
614 r = kill(pid, SIGKILL);
615 pid_remove(pid); 690 pid_remove(pid);
616 691
692 TRACE_KILL_END();
693
617 if (r) { 694 if (r) {
618 ALOGE("kill(%d): errno=%d", pid, errno); 695 ALOGE("kill(%d): errno=%d", pid, errno);
619 return -1; 696 return -1;
@@ -623,31 +700,40 @@ static int kill_one_process(struct proc* procp, int min_score_adj, bool is_criti
623} 700}
624 701
625/* 702/*
626 * Find a process to kill based on the current (possibly estimated) free memory 703 * Find processes to kill to free required number of pages.
627 * and cached memory sizes. Returns the size of the killed processes. 704 * If pages_to_free is set to 0 only one process will be killed.
705 * Returns the size of the killed processes.
628 */ 706 */
629static int find_and_kill_process(bool is_critical) { 707static int find_and_kill_processes(enum vmpressure_level level,
708 int pages_to_free) {
630 int i; 709 int i;
631 int killed_size = 0; 710 int killed_size;
632 int min_score_adj = is_critical ? critical_oomadj : medium_oomadj; 711 int pages_freed = 0;
712 int min_score_adj = level_oomadj[level];
633 713
634 for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) { 714 for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) {
635 struct proc *procp; 715 struct proc *procp;
636 716
637retry: 717 while (true) {
638 procp = proc_adj_lru(i); 718 if (is_go_device)
639 719 procp = proc_adj_lru(i);
640 if (procp) { 720 else
641 killed_size = kill_one_process(procp, min_score_adj, is_critical); 721 procp = proc_get_heaviest(i);
642 if (killed_size < 0) { 722
643 goto retry; 723 if (!procp)
644 } else { 724 break;
645 return killed_size; 725
726 killed_size = kill_one_process(procp, min_score_adj, level);
727 if (killed_size >= 0) {
728 pages_freed += killed_size;
729 if (pages_freed >= pages_to_free) {
730 return pages_freed;
731 }
646 } 732 }
647 } 733 }
648 } 734 }
649 735
650 return 0; 736 return pages_freed;
651} 737}
652 738
653static int64_t get_memory_usage(const char* path) { 739static int64_t get_memory_usage(const char* path) {
@@ -674,33 +760,118 @@ static int64_t get_memory_usage(const char* path) {
674 return mem_usage; 760 return mem_usage;
675} 761}
676 762
677static void mp_event_common(bool is_critical) { 763void record_low_pressure_levels(struct mem_size *free_mem) {
764 if (low_pressure_mem.min_free == -1 ||
765 low_pressure_mem.min_free > free_mem->free_mem) {
766 if (debug_process_killing) {
767 ALOGI("Low pressure min memory update from %d to %d",
768 low_pressure_mem.min_free, free_mem->free_mem);
769 }
770 low_pressure_mem.min_free = free_mem->free_mem;
771 }
772 /*
773 * Free memory at low vmpressure events occasionally gets spikes,
774 * possibly a stale low vmpressure event with memory already
775 * freed up (no memory pressure should have been reported).
776 * Ignore large jumps in max_free that would mess up our stats.
777 */
778 if (low_pressure_mem.max_free == -1 ||
779 (low_pressure_mem.max_free < free_mem->free_mem &&
780 free_mem->free_mem - low_pressure_mem.max_free < low_pressure_mem.max_free * 0.1)) {
781 if (debug_process_killing) {
782 ALOGI("Low pressure max memory update from %d to %d",
783 low_pressure_mem.max_free, free_mem->free_mem);
784 }
785 low_pressure_mem.max_free = free_mem->free_mem;
786 }
787}
788
789enum vmpressure_level upgrade_level(enum vmpressure_level level) {
790 return (enum vmpressure_level)((level < VMPRESS_LEVEL_CRITICAL) ?
791 level + 1 : level);
792}
793
794enum vmpressure_level downgrade_level(enum vmpressure_level level) {
795 return (enum vmpressure_level)((level > VMPRESS_LEVEL_LOW) ?
796 level - 1 : level);
797}
798
799static inline unsigned long get_time_diff_ms(struct timeval *from,
800 struct timeval *to) {
801 return (to->tv_sec - from->tv_sec) * 1000 +
802 (to->tv_usec - from->tv_usec) / 1000;
803}
804
805static void mp_event_common(enum vmpressure_level level) {
678 int ret; 806 int ret;
679 unsigned long long evcount; 807 unsigned long long evcount;
680 int index = is_critical ? CRITICAL_INDEX : MEDIUM_INDEX;
681 int64_t mem_usage, memsw_usage; 808 int64_t mem_usage, memsw_usage;
682 int64_t mem_pressure; 809 int64_t mem_pressure;
810 enum vmpressure_level lvl;
811 struct mem_size free_mem;
812 static struct timeval last_report_tm;
813 static unsigned long skip_count = 0;
814
815 /*
816 * Check all event counters from low to critical
817 * and upgrade to the highest priority one. By reading
818 * eventfd we also reset the event counters.
819 */
820 for (lvl = VMPRESS_LEVEL_LOW; lvl < VMPRESS_LEVEL_COUNT; lvl++) {
821 if (mpevfd[lvl] != -1 &&
822 read(mpevfd[lvl], &evcount, sizeof(evcount)) > 0 &&
823 evcount > 0 && lvl > level) {
824 level = lvl;
825 }
826 }
827
828 if (kill_timeout_ms) {
829 struct timeval curr_tm;
830 gettimeofday(&curr_tm, NULL);
831 if (get_time_diff_ms(&last_report_tm, &curr_tm) < kill_timeout_ms) {
832 skip_count++;
833 return;
834 }
835 }
836
837 if (skip_count > 0) {
838 if (debug_process_killing) {
839 ALOGI("%lu memory pressure events were skipped after a kill!",
840 skip_count);
841 }
842 skip_count = 0;
843 }
683 844
684 ret = read(mpevfd[index], &evcount, sizeof(evcount)); 845 if (get_free_memory(&free_mem) == 0) {
685 if (ret < 0) 846 if (level == VMPRESS_LEVEL_LOW) {
686 ALOGE("Error reading memory pressure event fd; errno=%d", 847 record_low_pressure_levels(&free_mem);
687 errno); 848 }
849 } else {
850 ALOGE("Failed to get free memory!");
851 return;
852 }
853
854 if (level_oomadj[level] > OOM_SCORE_ADJ_MAX) {
855 /* Do not monitor this pressure level */
856 return;
857 }
688 858
689 mem_usage = get_memory_usage(MEMCG_MEMORY_USAGE); 859 mem_usage = get_memory_usage(MEMCG_MEMORY_USAGE);
690 memsw_usage = get_memory_usage(MEMCG_MEMORYSW_USAGE); 860 memsw_usage = get_memory_usage(MEMCG_MEMORYSW_USAGE);
691 if (memsw_usage < 0 || mem_usage < 0) { 861 if (memsw_usage < 0 || mem_usage < 0) {
692 find_and_kill_process(is_critical); 862 goto do_kill;
693 return;
694 } 863 }
695 864
696 // Calculate percent for swappinness. 865 // Calculate percent for swappinness.
697 mem_pressure = (mem_usage * 100) / memsw_usage; 866 mem_pressure = (mem_usage * 100) / memsw_usage;
698 867
699 if (enable_pressure_upgrade && !is_critical) { 868 if (enable_pressure_upgrade && level != VMPRESS_LEVEL_CRITICAL) {
700 // We are swapping too much. 869 // We are swapping too much.
701 if (mem_pressure < upgrade_pressure) { 870 if (mem_pressure < upgrade_pressure) {
702 ALOGI("Event upgraded to critical."); 871 level = upgrade_level(level);
703 is_critical = true; 872 if (debug_process_killing) {
873 ALOGI("Event upgraded to %s", level_name[level]);
874 }
704 } 875 }
705 } 876 }
706 877
@@ -708,41 +879,74 @@ static void mp_event_common(bool is_critical) {
708 // kill any process, since enough memory is available. 879 // kill any process, since enough memory is available.
709 if (mem_pressure > downgrade_pressure) { 880 if (mem_pressure > downgrade_pressure) {
710 if (debug_process_killing) { 881 if (debug_process_killing) {
711 ALOGI("Ignore %s memory pressure", is_critical ? "critical" : "medium"); 882 ALOGI("Ignore %s memory pressure", level_name[level]);
712 } 883 }
713 return; 884 return;
714 } else if (is_critical && mem_pressure > upgrade_pressure) { 885 } else if (level == VMPRESS_LEVEL_CRITICAL &&
886 mem_pressure > upgrade_pressure) {
715 if (debug_process_killing) { 887 if (debug_process_killing) {
716 ALOGI("Downgrade critical memory pressure"); 888 ALOGI("Downgrade critical memory pressure");
717 } 889 }
718 // Downgrade event to medium, since enough memory available. 890 // Downgrade event, since enough memory available.
719 is_critical = false; 891 level = downgrade_level(level);
720 } 892 }
721 893
722 if (find_and_kill_process(is_critical) == 0) { 894do_kill:
723 if (debug_process_killing) { 895 if (is_go_device) {
724 ALOGI("Nothing to kill"); 896 /* For Go devices kill only one task */
897 if (find_and_kill_processes(level, 0) == 0) {
898 if (debug_process_killing) {
899 ALOGI("Nothing to kill");
900 }
901 }
902 } else {
903 /* If pressure level is less than critical and enough free swap then ignore */
904 if (level < VMPRESS_LEVEL_CRITICAL && free_mem.free_swap > low_pressure_mem.max_free) {
905 if (debug_process_killing) {
906 ALOGI("Ignoring pressure since %d swap pages are available ", free_mem.free_swap);
907 }
908 return;
909 }
910
911 /* Free up enough memory to downgrate the memory pressure to low level */
912 if (free_mem.free_mem < low_pressure_mem.max_free) {
913 int pages_to_free = low_pressure_mem.max_free - free_mem.free_mem;
914 if (debug_process_killing) {
915 ALOGI("Trying to free %d pages", pages_to_free);
916 }
917 int pages_freed = find_and_kill_processes(level, pages_to_free);
918 if (pages_freed < pages_to_free) {
919 if (debug_process_killing) {
920 ALOGI("Unable to free enough memory (pages freed=%d)",
921 pages_freed);
922 }
923 } else {
924 gettimeofday(&last_report_tm, NULL);
925 }
725 } 926 }
726 } 927 }
727} 928}
728 929
729static void mp_event(uint32_t events __unused) { 930static void mp_event_low(uint32_t events __unused) {
730 mp_event_common(false); 931 mp_event_common(VMPRESS_LEVEL_LOW);
932}
933
934static void mp_event_medium(uint32_t events __unused) {
935 mp_event_common(VMPRESS_LEVEL_MEDIUM);
731} 936}
732 937
733static void mp_event_critical(uint32_t events __unused) { 938static void mp_event_critical(uint32_t events __unused) {
734 mp_event_common(true); 939 mp_event_common(VMPRESS_LEVEL_CRITICAL);
735} 940}
736 941
737static int init_mp_common(char *levelstr, void *event_handler, bool is_critical) 942static bool init_mp_common(void *event_handler, enum vmpressure_level level) {
738{
739 int mpfd; 943 int mpfd;
740 int evfd; 944 int evfd;
741 int evctlfd; 945 int evctlfd;
742 char buf[256]; 946 char buf[256];
743 struct epoll_event epev; 947 struct epoll_event epev;
744 int ret; 948 int ret;
745 int mpevfd_index = is_critical ? CRITICAL_INDEX : MEDIUM_INDEX; 949 const char *levelstr = level_name[level];
746 950
747 mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY | O_CLOEXEC); 951 mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY | O_CLOEXEC);
748 if (mpfd < 0) { 952 if (mpfd < 0) {
@@ -783,8 +987,9 @@ static int init_mp_common(char *levelstr, void *event_handler, bool is_critical)
783 goto err; 987 goto err;
784 } 988 }
785 maxevents++; 989 maxevents++;
786 mpevfd[mpevfd_index] = evfd; 990 mpevfd[level] = evfd;
787 return 0; 991 close(evctlfd);
992 return true;
788 993
789err: 994err:
790 close(evfd); 995 close(evfd);
@@ -793,17 +998,7 @@ err_eventfd:
793err_open_evctlfd: 998err_open_evctlfd:
794 close(mpfd); 999 close(mpfd);
795err_open_mpfd: 1000err_open_mpfd:
796 return -1; 1001 return false;
797}
798
799static int init_mp_medium()
800{
801 return init_mp_common(MEMPRESSURE_WATCH_MEDIUM_LEVEL, (void *)&mp_event, false);
802}
803
804static int init_mp_critical()
805{
806 return init_mp_common(MEMPRESSURE_WATCH_CRITICAL_LEVEL, (void *)&mp_event_critical, true);
807} 1002}
808 1003
809static int init(void) { 1004static int init(void) {
@@ -843,15 +1038,18 @@ static int init(void) {
843 maxevents++; 1038 maxevents++;
844 1039
845 has_inkernel_module = !access(INKERNEL_MINFREE_PATH, W_OK); 1040 has_inkernel_module = !access(INKERNEL_MINFREE_PATH, W_OK);
846 use_inkernel_interface = has_inkernel_module && !is_go_device; 1041 use_inkernel_interface = has_inkernel_module;
847 1042
848 if (use_inkernel_interface) { 1043 if (use_inkernel_interface) {
849 ALOGI("Using in-kernel low memory killer interface"); 1044 ALOGI("Using in-kernel low memory killer interface");
850 } else { 1045 } else {
851 ret = init_mp_medium(); 1046 if (!init_mp_common((void *)&mp_event_low, VMPRESS_LEVEL_LOW) ||
852 ret |= init_mp_critical(); 1047 !init_mp_common((void *)&mp_event_medium, VMPRESS_LEVEL_MEDIUM) ||
853 if (ret) 1048 !init_mp_common((void *)&mp_event_critical,
1049 VMPRESS_LEVEL_CRITICAL)) {
854 ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer"); 1050 ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer");
1051 return -1;
1052 }
855 } 1053 }
856 1054
857 for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) { 1055 for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) {
@@ -892,13 +1090,27 @@ int main(int argc __unused, char **argv __unused) {
892 .sched_priority = 1, 1090 .sched_priority = 1,
893 }; 1091 };
894 1092
895 medium_oomadj = property_get_int32("ro.lmk.medium", 800); 1093 /* By default disable low level vmpressure events */
896 critical_oomadj = property_get_int32("ro.lmk.critical", 0); 1094 level_oomadj[VMPRESS_LEVEL_LOW] =
1095 property_get_int32("ro.lmk.low", OOM_SCORE_ADJ_MAX + 1);
1096 level_oomadj[VMPRESS_LEVEL_MEDIUM] =
1097 property_get_int32("ro.lmk.medium", 800);
1098 level_oomadj[VMPRESS_LEVEL_CRITICAL] =
1099 property_get_int32("ro.lmk.critical", 0);
897 debug_process_killing = property_get_bool("ro.lmk.debug", false); 1100 debug_process_killing = property_get_bool("ro.lmk.debug", false);
898 enable_pressure_upgrade = property_get_bool("ro.lmk.critical_upgrade", false); 1101
899 upgrade_pressure = (int64_t)property_get_int32("ro.lmk.upgrade_pressure", 50); 1102 /* By default disable upgrade/downgrade logic */
900 downgrade_pressure = (int64_t)property_get_int32("ro.lmk.downgrade_pressure", 60); 1103 enable_pressure_upgrade =
1104 property_get_bool("ro.lmk.critical_upgrade", false);
1105 upgrade_pressure =
1106 (int64_t)property_get_int32("ro.lmk.upgrade_pressure", 100);
1107 downgrade_pressure =
1108 (int64_t)property_get_int32("ro.lmk.downgrade_pressure", 100);
1109 kill_heaviest_task =
1110 property_get_bool("ro.lmk.kill_heaviest_task", true);
901 is_go_device = property_get_bool("ro.config.low_ram", false); 1111 is_go_device = property_get_bool("ro.config.low_ram", false);
1112 kill_timeout_ms =
1113 (unsigned long)property_get_int32("ro.lmk.kill_timeout_ms", 0);
902 1114
903 // MCL_ONFAULT pins pages as they fault instead of loading 1115 // MCL_ONFAULT pins pages as they fault instead of loading
904 // everything immediately all at once. (Which would be bad, 1116 // everything immediately all at once. (Which would be bad,
diff --git a/logcat/Android.bp b/logcat/Android.bp
index afc7a0182..01beb53e8 100644
--- a/logcat/Android.bp
+++ b/logcat/Android.bp
@@ -68,8 +68,11 @@ cc_prebuilt_binary {
68 srcs: ["logpersist"], 68 srcs: ["logpersist"],
69 init_rc: ["logcatd.rc"], 69 init_rc: ["logcatd.rc"],
70 required: ["logcatd"], 70 required: ["logcatd"],
71 symlinks: ["logpersist.stop", "logpersist.cat"], 71 symlinks: [
72 "logpersist.stop",
73 "logpersist.cat",
74 ],
72 strip: { 75 strip: {
73 none: true, 76 none: true,
74 } 77 },
75} 78}
diff --git a/logd/Android.bp b/logd/Android.bp
index 68b79d32e..5c79976a3 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -25,7 +25,7 @@ event_flag = [
25 "-DAUDITD_LOG_TAG=1003", 25 "-DAUDITD_LOG_TAG=1003",
26 "-DCHATTY_LOG_TAG=1004", 26 "-DCHATTY_LOG_TAG=1004",
27 "-DTAG_DEF_LOG_TAG=1005", 27 "-DTAG_DEF_LOG_TAG=1005",
28 "-DLIBLOG_LOG_TAG=1006" 28 "-DLIBLOG_LOG_TAG=1006",
29] 29]
30 30
31cc_library_static { 31cc_library_static {
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 560f490cf..b8af2f09b 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -198,7 +198,7 @@ static enum match_type identical(LogBufferElement* elem,
198 198
199int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, 199int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
200 pid_t tid, const char* msg, unsigned short len) { 200 pid_t tid, const char* msg, unsigned short len) {
201 if ((log_id >= LOG_ID_MAX) || (log_id < 0)) { 201 if (log_id >= LOG_ID_MAX) {
202 return -EINVAL; 202 return -EINVAL;
203 } 203 }
204 204
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
index ccb1aa609..f163f576b 100644
--- a/logwrapper/Android.bp
+++ b/logwrapper/Android.bp
@@ -49,5 +49,5 @@ cc_benchmark {
49 ], 49 ],
50 cflags: [ 50 cflags: [
51 "-Werror", 51 "-Werror",
52 ] 52 ],
53} 53}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index f4509a42d..feb100ef6 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -145,13 +145,21 @@ endef
145# $(1): Input source file (ld.config.txt) 145# $(1): Input source file (ld.config.txt)
146# $(2): Output built module 146# $(2): Output built module
147# $(3): VNDK version suffix 147# $(3): VNDK version suffix
148# $(4): true if libz must be included in llndk not in vndk-sp
148define update_and_install_ld_config 149define update_and_install_ld_config
150# If $(4) is true, move libz to llndk from vndk-sp.
151$(if $(filter true,$(4)),\
152 $(eval llndk_libraries_list := $(LLNDK_LIBRARIES) libz) \
153 $(eval vndksp_libraries_list := $(filter-out libz,$(VNDK_SAMEPROCESS_LIBRARIES))),\
154 $(eval llndk_libraries_list := $(LLNDK_LIBRARIES)) \
155 $(eval vndksp_libraries_list := $(VNDK_SAMEPROCESS_LIBRARIES)))
156
149llndk_libraries := $(call normalize-path-list,$(addsuffix .so,\ 157llndk_libraries := $(call normalize-path-list,$(addsuffix .so,\
150 $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(LLNDK_LIBRARIES)))) 158 $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(llndk_libraries_list))))
151private_llndk_libraries := $(call normalize-path-list,$(addsuffix .so,\ 159private_llndk_libraries := $(call normalize-path-list,$(addsuffix .so,\
152 $(filter $(VNDK_PRIVATE_LIBRARIES),$(LLNDK_LIBRARIES)))) 160 $(filter $(VNDK_PRIVATE_LIBRARIES),$(llndk_libraries_list))))
153vndk_sameprocess_libraries := $(call normalize-path-list,$(addsuffix .so,\ 161vndk_sameprocess_libraries := $(call normalize-path-list,$(addsuffix .so,\
154 $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(VNDK_SAMEPROCESS_LIBRARIES)))) 162 $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(vndksp_libraries_list))))
155vndk_core_libraries := $(call normalize-path-list,$(addsuffix .so,\ 163vndk_core_libraries := $(call normalize-path-list,$(addsuffix .so,\
156 $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(VNDK_CORE_LIBRARIES)))) 164 $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(VNDK_CORE_LIBRARIES))))
157sanitizer_runtime_libraries := $(call normalize-path-list,$(addsuffix .so,\ 165sanitizer_runtime_libraries := $(call normalize-path-list,$(addsuffix .so,\
@@ -180,6 +188,8 @@ $(2): $(1)
180 $$(hide) sed -i -e 's?%SANITIZER_RUNTIME_LIBRARIES%?$$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES)?g' $$@ 188 $$(hide) sed -i -e 's?%SANITIZER_RUNTIME_LIBRARIES%?$$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES)?g' $$@
181 $$(hide) sed -i -e 's?%VNDK_VER%?$$(PRIVATE_VNDK_VERSION)?g' $$@ 189 $$(hide) sed -i -e 's?%VNDK_VER%?$$(PRIVATE_VNDK_VERSION)?g' $$@
182 190
191llndk_libraries_list :=
192vndksp_libraries_list :=
183llndk_libraries := 193llndk_libraries :=
184private_llndk_libraries := 194private_llndk_libraries :=
185vndk_sameprocess_libraries := 195vndk_sameprocess_libraries :=
@@ -228,7 +238,8 @@ include $(BUILD_SYSTEM)/base_rules.mk
228$(eval $(call update_and_install_ld_config,\ 238$(eval $(call update_and_install_ld_config,\
229 $(LOCAL_PATH)/etc/ld.config.vndk_lite.txt,\ 239 $(LOCAL_PATH)/etc/ld.config.vndk_lite.txt,\
230 $(LOCAL_BUILT_MODULE),\ 240 $(LOCAL_BUILT_MODULE),\
231 $(if $(BOARD_VNDK_VERSION),$(PLATFORM_VNDK_VERSION)))) 241 $(if $(BOARD_VNDK_VERSION),$(PLATFORM_VNDK_VERSION)),\
242 true))
232 243
233else 244else
234# for legacy non-treblized devices 245# for legacy non-treblized devices
@@ -258,7 +269,8 @@ include $(BUILD_SYSTEM)/base_rules.mk
258$(eval $(call update_and_install_ld_config,\ 269$(eval $(call update_and_install_ld_config,\
259 $(LOCAL_PATH)/etc/ld.config.vndk_lite.txt,\ 270 $(LOCAL_PATH)/etc/ld.config.vndk_lite.txt,\
260 $(LOCAL_BUILT_MODULE),\ 271 $(LOCAL_BUILT_MODULE),\
261 $(PLATFORM_VNDK_VERSION))) 272 $(PLATFORM_VNDK_VERSION),\
273 true))
262 274
263####################################### 275#######################################
264# llndk.libraries.txt 276# llndk.libraries.txt
diff --git a/rootdir/init.rc b/rootdir/init.rc
index f008c1748..a213ffb39 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -82,10 +82,10 @@ on init
82 82
83 # Mount staging areas for devices managed by vold 83 # Mount staging areas for devices managed by vold
84 # See storage config details at http://source.android.com/tech/storage/ 84 # See storage config details at http://source.android.com/tech/storage/
85 mount tmpfs tmpfs /mnt mode=0755,uid=0,gid=1000 85 mount tmpfs tmpfs /mnt nodev noexec nosuid mode=0755,uid=0,gid=1000
86 restorecon_recursive /mnt 86 restorecon_recursive /mnt
87 87
88 mount configfs none /config 88 mount configfs none /config nodev noexec nosuid
89 chmod 0775 /config/sdcardfs 89 chmod 0775 /config/sdcardfs
90 chown system package_info /config/sdcardfs 90 chown system package_info /config/sdcardfs
91 91
@@ -318,8 +318,9 @@ on post-fs
318 start hwservicemanager 318 start hwservicemanager
319 start vndservicemanager 319 start vndservicemanager
320 320
321 # once everything is setup, no need to modify / 321 # Once everything is setup, no need to modify /.
322 mount rootfs rootfs / ro remount 322 # The bind+ro combination avoids modifying any other mount flags.
323 mount rootfs rootfs / remount bind ro
323 # Mount shared so changes propagate into child namespaces 324 # Mount shared so changes propagate into child namespaces
324 mount rootfs rootfs / shared rec 325 mount rootfs rootfs / shared rec
325 # Mount default storage into root namespace 326 # Mount default storage into root namespace
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 322a63d28..5428e733e 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -31,7 +31,10 @@ cc_binary {
31 "trusty_keymaster_ipc.cpp", 31 "trusty_keymaster_ipc.cpp",
32 "trusty_keymaster_main.cpp", 32 "trusty_keymaster_main.cpp",
33 ], 33 ],
34 cflags: ["-Wall", "-Werror"], 34 cflags: [
35 "-Wall",
36 "-Werror",
37 ],
35 shared_libs: [ 38 shared_libs: [
36 "libcrypto", 39 "libcrypto",
37 "libcutils", 40 "libcutils",
diff --git a/trusty/libtrusty/Android.bp b/trusty/libtrusty/Android.bp
index c48deed1c..f6e9bee3d 100644
--- a/trusty/libtrusty/Android.bp
+++ b/trusty/libtrusty/Android.bp
@@ -22,7 +22,10 @@ cc_library {
22 22
23 srcs: ["trusty.c"], 23 srcs: ["trusty.c"],
24 export_include_dirs: ["include"], 24 export_include_dirs: ["include"],
25 cflags: ["-Wall", "-Werror"], 25 cflags: [
26 "-Wall",
27 "-Werror",
28 ],
26 29
27 shared_libs: ["liblog"], 30 shared_libs: ["liblog"],
28} 31}
diff --git a/trusty/libtrusty/tipc-test/Android.bp b/trusty/libtrusty/tipc-test/Android.bp
index 1e8467f0f..32499e3f1 100644
--- a/trusty/libtrusty/tipc-test/Android.bp
+++ b/trusty/libtrusty/tipc-test/Android.bp
@@ -25,5 +25,8 @@ cc_test {
25 "liblog", 25 "liblog",
26 ], 26 ],
27 gtest: false, 27 gtest: false,
28 cflags: ["-Wall", "-Werror"], 28 cflags: [
29 "-Wall",
30 "-Werror",
31 ],
29} 32}
diff --git a/trusty/storage/lib/Android.bp b/trusty/storage/lib/Android.bp
index 4e41674bd..2fba17edd 100644
--- a/trusty/storage/lib/Android.bp
+++ b/trusty/storage/lib/Android.bp
@@ -34,5 +34,5 @@ cc_library_static {
34 "-fvisibility=hidden", 34 "-fvisibility=hidden",
35 "-Wall", 35 "-Wall",
36 "-Werror", 36 "-Werror",
37 ] 37 ],
38} 38}
diff --git a/trusty/storage/proxy/Android.bp b/trusty/storage/proxy/Android.bp
index da8542d5a..b93facbbc 100644
--- a/trusty/storage/proxy/Android.bp
+++ b/trusty/storage/proxy/Android.bp
@@ -36,5 +36,5 @@ cc_binary {
36 cflags: [ 36 cflags: [
37 "-Wall", 37 "-Wall",
38 "-Werror", 38 "-Werror",
39 ] 39 ],
40} 40}
diff --git a/usbd/Android.bp b/usbd/Android.bp
index 4f9338fef..3afa7a951 100644
--- a/usbd/Android.bp
+++ b/usbd/Android.bp
@@ -13,4 +13,3 @@ cc_binary {
13 "libcutils", 13 "libcutils",
14 ], 14 ],
15} 15}
16