blob: ed87f9ed770ae2d0e2263650a21426b3155a4500 [file] [log] [blame]
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import collections
import contextlib
import logging
import os
import re
import shutil
import tempfile
import unittest
from pylib.symbols import apk_native_libs_unittest
from pylib.symbols import mock_addr2line
from pylib.symbols import symbol_utils
_MOCK_ELF_DATA = apk_native_libs_unittest.MOCK_ELF_DATA
_MOCK_A2L_PATH = os.path.join(os.path.dirname(mock_addr2line.__file__),
'mock_addr2line')
# pylint: disable=line-too-long
# list of (start_offset, end_offset, size, libpath) tuples corresponding
# to the content of base.apk. This was taken from an x86 ChromeModern.apk
# component build.
_TEST_APK_LIBS = [
(0x01331000, 0x013696bc, 0x000386bc, 'libaccessibility.cr.so'),
(0x0136a000, 0x013779c4, 0x0000d9c4, 'libanimation.cr.so'),
(0x01378000, 0x0137f7e8, 0x000077e8, 'libapdu.cr.so'),
(0x01380000, 0x0155ccc8, 0x001dccc8, 'libbase.cr.so'),
(0x0155d000, 0x015ab98c, 0x0004e98c, 'libbase_i18n.cr.so'),
(0x015ac000, 0x015dff4c, 0x00033f4c, 'libbindings.cr.so'),
(0x015e0000, 0x015f5a54, 0x00015a54, 'libbindings_base.cr.so'),
(0x0160e000, 0x01731960, 0x00123960, 'libblink_common.cr.so'),
(0x01732000, 0x0174ce54, 0x0001ae54, 'libblink_controller.cr.so'),
(0x0174d000, 0x0318c528, 0x01a3f528, 'libblink_core.cr.so'),
(0x0318d000, 0x03191700, 0x00004700, 'libblink_mojom_broadcastchannel_bindings_shared.cr.so'),
(0x03192000, 0x03cd7918, 0x00b45918, 'libblink_modules.cr.so'),
(0x03cd8000, 0x03d137d0, 0x0003b7d0, 'libblink_mojo_bindings_shared.cr.so'),
(0x03d14000, 0x03d2670c, 0x0001270c, 'libblink_offscreen_canvas_mojo_bindings_shared.cr.so'),
(0x03d27000, 0x046c7054, 0x009a0054, 'libblink_platform.cr.so'),
(0x046c8000, 0x0473fbfc, 0x00077bfc, 'libbluetooth.cr.so'),
(0x04740000, 0x04878f40, 0x00138f40, 'libboringssl.cr.so'),
(0x04879000, 0x0498466c, 0x0010b66c, 'libc++_shared.so'),
(0x04985000, 0x0498d93c, 0x0000893c, 'libcaptive_portal.cr.so'),
(0x0498e000, 0x049947cc, 0x000067cc, 'libcapture_base.cr.so'),
(0x04995000, 0x04b39f18, 0x001a4f18, 'libcapture_lib.cr.so'),
(0x04b3a000, 0x04b488ec, 0x0000e8ec, 'libcbor.cr.so'),
(0x04b49000, 0x04e9ea5c, 0x00355a5c, 'libcc.cr.so'),
(0x04e9f000, 0x04ed6404, 0x00037404, 'libcc_animation.cr.so'),
(0x04ed7000, 0x04ef5ab4, 0x0001eab4, 'libcc_base.cr.so'),
(0x04ef6000, 0x04fd9364, 0x000e3364, 'libcc_blink.cr.so'),
(0x04fda000, 0x04fe2758, 0x00008758, 'libcc_debug.cr.so'),
(0x04fe3000, 0x0500ae0c, 0x00027e0c, 'libcc_ipc.cr.so'),
(0x0500b000, 0x05078f38, 0x0006df38, 'libcc_paint.cr.so'),
(0x05079000, 0x0507e734, 0x00005734, 'libcdm_manager.cr.so'),
(0x0507f000, 0x06f4d744, 0x01ece744, 'libchrome.cr.so'),
(0x06f54000, 0x06feb830, 0x00097830, 'libchromium_sqlite3.cr.so'),
(0x06fec000, 0x0706f554, 0x00083554, 'libclient.cr.so'),
(0x07070000, 0x0708da60, 0x0001da60, 'libcloud_policy_proto_generated_compile.cr.so'),
(0x0708e000, 0x07121f28, 0x00093f28, 'libcodec.cr.so'),
(0x07122000, 0x07134ab8, 0x00012ab8, 'libcolor_space.cr.so'),
(0x07135000, 0x07138614, 0x00003614, 'libcommon.cr.so'),
(0x07139000, 0x0717c938, 0x00043938, 'libcompositor.cr.so'),
(0x0717d000, 0x0923d78c, 0x020c078c, 'libcontent.cr.so'),
(0x0923e000, 0x092ae87c, 0x0007087c, 'libcontent_common_mojo_bindings_shared.cr.so'),
(0x092af000, 0x092be718, 0x0000f718, 'libcontent_public_common_mojo_bindings_shared.cr.so'),
(0x092bf000, 0x092d9a20, 0x0001aa20, 'libcrash_key.cr.so'),
(0x092da000, 0x092eda58, 0x00013a58, 'libcrcrypto.cr.so'),
(0x092ee000, 0x092f16e0, 0x000036e0, 'libdevice_base.cr.so'),
(0x092f2000, 0x092fe8d8, 0x0000c8d8, 'libdevice_event_log.cr.so'),
(0x092ff000, 0x093026a4, 0x000036a4, 'libdevice_features.cr.so'),
(0x09303000, 0x093f1220, 0x000ee220, 'libdevice_gamepad.cr.so'),
(0x093f2000, 0x09437f54, 0x00045f54, 'libdevice_vr_mojo_bindings.cr.so'),
(0x09438000, 0x0954c168, 0x00114168, 'libdevice_vr_mojo_bindings_blink.cr.so'),
(0x0954d000, 0x0955d720, 0x00010720, 'libdevice_vr_mojo_bindings_shared.cr.so'),
(0x0955e000, 0x0956b9c0, 0x0000d9c0, 'libdevices.cr.so'),
(0x0956c000, 0x0957cae8, 0x00010ae8, 'libdiscardable_memory_client.cr.so'),
(0x0957d000, 0x09588854, 0x0000b854, 'libdiscardable_memory_common.cr.so'),
(0x09589000, 0x0959cbb4, 0x00013bb4, 'libdiscardable_memory_service.cr.so'),
(0x0959d000, 0x095b6b90, 0x00019b90, 'libdisplay.cr.so'),
(0x095b7000, 0x095be930, 0x00007930, 'libdisplay_types.cr.so'),
(0x095bf000, 0x095c46c4, 0x000056c4, 'libdisplay_util.cr.so'),
(0x095c5000, 0x095f54a4, 0x000304a4, 'libdomain_reliability.cr.so'),
(0x095f6000, 0x0966fe08, 0x00079e08, 'libembedder.cr.so'),
(0x09670000, 0x096735f8, 0x000035f8, 'libembedder_switches.cr.so'),
(0x09674000, 0x096a3460, 0x0002f460, 'libevents.cr.so'),
(0x096a4000, 0x096b6d40, 0x00012d40, 'libevents_base.cr.so'),
(0x096b7000, 0x0981a778, 0x00163778, 'libffmpeg.cr.so'),
(0x0981b000, 0x09945c94, 0x0012ac94, 'libfido.cr.so'),
(0x09946000, 0x09a330dc, 0x000ed0dc, 'libfingerprint.cr.so'),
(0x09a34000, 0x09b53170, 0x0011f170, 'libfreetype_harfbuzz.cr.so'),
(0x09b54000, 0x09bc5c5c, 0x00071c5c, 'libgcm.cr.so'),
(0x09bc6000, 0x09cc8584, 0x00102584, 'libgeolocation.cr.so'),
(0x09cc9000, 0x09cdc8d4, 0x000138d4, 'libgeometry.cr.so'),
(0x09cdd000, 0x09cec8b4, 0x0000f8b4, 'libgeometry_skia.cr.so'),
(0x09ced000, 0x09d10e14, 0x00023e14, 'libgesture_detection.cr.so'),
(0x09d11000, 0x09d7595c, 0x0006495c, 'libgfx.cr.so'),
(0x09d76000, 0x09d7d7cc, 0x000077cc, 'libgfx_ipc.cr.so'),
(0x09d7e000, 0x09d82708, 0x00004708, 'libgfx_ipc_buffer_types.cr.so'),
(0x09d83000, 0x09d89748, 0x00006748, 'libgfx_ipc_color.cr.so'),
(0x09d8a000, 0x09d8f6f4, 0x000056f4, 'libgfx_ipc_geometry.cr.so'),
(0x09d90000, 0x09d94754, 0x00004754, 'libgfx_ipc_skia.cr.so'),
(0x09d95000, 0x09d9869c, 0x0000369c, 'libgfx_switches.cr.so'),
(0x09d99000, 0x09dba0ac, 0x000210ac, 'libgin.cr.so'),
(0x09dbb000, 0x09e0a8cc, 0x0004f8cc, 'libgl_in_process_context.cr.so'),
(0x09e0b000, 0x09e17a18, 0x0000ca18, 'libgl_init.cr.so'),
(0x09e18000, 0x09ee34e4, 0x000cb4e4, 'libgl_wrapper.cr.so'),
(0x09ee4000, 0x0a1a2e00, 0x002bee00, 'libgles2.cr.so'),
(0x0a1a3000, 0x0a24556c, 0x000a256c, 'libgles2_implementation.cr.so'),
(0x0a246000, 0x0a267038, 0x00021038, 'libgles2_utils.cr.so'),
(0x0a268000, 0x0a3288e4, 0x000c08e4, 'libgpu.cr.so'),
(0x0a329000, 0x0a3627ec, 0x000397ec, 'libgpu_ipc_service.cr.so'),
(0x0a363000, 0x0a388a18, 0x00025a18, 'libgpu_util.cr.so'),
(0x0a389000, 0x0a506d8c, 0x0017dd8c, 'libhost.cr.so'),
(0x0a507000, 0x0a6f0ec0, 0x001e9ec0, 'libicui18n.cr.so'),
(0x0a6f1000, 0x0a83b4c8, 0x0014a4c8, 'libicuuc.cr.so'),
(0x0a83c000, 0x0a8416e4, 0x000056e4, 'libinterfaces_shared.cr.so'),
(0x0a842000, 0x0a87e2a0, 0x0003c2a0, 'libipc.cr.so'),
(0x0a87f000, 0x0a88c98c, 0x0000d98c, 'libipc_mojom.cr.so'),
(0x0a88d000, 0x0a8926e4, 0x000056e4, 'libipc_mojom_shared.cr.so'),
(0x0a893000, 0x0a8a1e18, 0x0000ee18, 'libkeyed_service_content.cr.so'),
(0x0a8a2000, 0x0a8b4a30, 0x00012a30, 'libkeyed_service_core.cr.so'),
(0x0a8b5000, 0x0a930a80, 0x0007ba80, 'libleveldatabase.cr.so'),
(0x0a931000, 0x0a9b3908, 0x00082908, 'libmanager.cr.so'),
(0x0a9b4000, 0x0aea9bb4, 0x004f5bb4, 'libmedia.cr.so'),
(0x0aeaa000, 0x0b08cb88, 0x001e2b88, 'libmedia_blink.cr.so'),
(0x0b08d000, 0x0b0a4728, 0x00017728, 'libmedia_devices_mojo_bindings_shared.cr.so'),
(0x0b0a5000, 0x0b1943ec, 0x000ef3ec, 'libmedia_gpu.cr.so'),
(0x0b195000, 0x0b2d07d4, 0x0013b7d4, 'libmedia_mojo_services.cr.so'),
(0x0b2d1000, 0x0b2d4760, 0x00003760, 'libmessage_center.cr.so'),
(0x0b2d5000, 0x0b2e0938, 0x0000b938, 'libmessage_support.cr.so'),
(0x0b2e1000, 0x0b2f3ad0, 0x00012ad0, 'libmetrics_cpp.cr.so'),
(0x0b2f4000, 0x0b313bb8, 0x0001fbb8, 'libmidi.cr.so'),
(0x0b314000, 0x0b31b848, 0x00007848, 'libmojo_base_lib.cr.so'),
(0x0b31c000, 0x0b3329f8, 0x000169f8, 'libmojo_base_mojom.cr.so'),
(0x0b333000, 0x0b34b98c, 0x0001898c, 'libmojo_base_mojom_blink.cr.so'),
(0x0b34c000, 0x0b354700, 0x00008700, 'libmojo_base_mojom_shared.cr.so'),
(0x0b355000, 0x0b3608b0, 0x0000b8b0, 'libmojo_base_shared_typemap_traits.cr.so'),
(0x0b361000, 0x0b3ad454, 0x0004c454, 'libmojo_edk.cr.so'),
(0x0b3ae000, 0x0b3c4a20, 0x00016a20, 'libmojo_edk_ports.cr.so'),
(0x0b3c5000, 0x0b3d38a0, 0x0000e8a0, 'libmojo_mojom_bindings.cr.so'),
(0x0b3d4000, 0x0b3da6e8, 0x000066e8, 'libmojo_mojom_bindings_shared.cr.so'),
(0x0b3db000, 0x0b3e27f0, 0x000077f0, 'libmojo_public_system.cr.so'),
(0x0b3e3000, 0x0b3fa9fc, 0x000179fc, 'libmojo_public_system_cpp.cr.so'),
(0x0b3fb000, 0x0b407728, 0x0000c728, 'libmojom_core_shared.cr.so'),
(0x0b408000, 0x0b421744, 0x00019744, 'libmojom_platform_shared.cr.so'),
(0x0b422000, 0x0b43451c, 0x0001251c, 'libnative_theme.cr.so'),
(0x0b435000, 0x0baaa1bc, 0x006751bc, 'libnet.cr.so'),
(0x0bac4000, 0x0bb74670, 0x000b0670, 'libnetwork_cpp.cr.so'),
(0x0bb75000, 0x0bbaee8c, 0x00039e8c, 'libnetwork_cpp_base.cr.so'),
(0x0bbaf000, 0x0bd21844, 0x00172844, 'libnetwork_service.cr.so'),
(0x0bd22000, 0x0bd256e4, 0x000036e4, 'libnetwork_session_configurator.cr.so'),
(0x0bd26000, 0x0bd33734, 0x0000d734, 'libonc.cr.so'),
(0x0bd34000, 0x0bd9ce18, 0x00068e18, 'libperfetto.cr.so'),
(0x0bd9d000, 0x0bda4854, 0x00007854, 'libplatform.cr.so'),
(0x0bda5000, 0x0bec5ce4, 0x00120ce4, 'libpolicy_component.cr.so'),
(0x0bec6000, 0x0bf5ab58, 0x00094b58, 'libpolicy_proto.cr.so'),
(0x0bf5b000, 0x0bf86fbc, 0x0002bfbc, 'libprefs.cr.so'),
(0x0bf87000, 0x0bfa5d74, 0x0001ed74, 'libprinting.cr.so'),
(0x0bfa6000, 0x0bfe0e80, 0x0003ae80, 'libprotobuf_lite.cr.so'),
(0x0bfe1000, 0x0bff0a18, 0x0000fa18, 'libproxy_config.cr.so'),
(0x0bff1000, 0x0c0f6654, 0x00105654, 'libpublic.cr.so'),
(0x0c0f7000, 0x0c0fa6a4, 0x000036a4, 'librange.cr.so'),
(0x0c0fb000, 0x0c118058, 0x0001d058, 'libraster.cr.so'),
(0x0c119000, 0x0c133d00, 0x0001ad00, 'libresource_coordinator_cpp.cr.so'),
(0x0c134000, 0x0c1396a0, 0x000056a0, 'libresource_coordinator_cpp_base.cr.so'),
(0x0c13a000, 0x0c1973b8, 0x0005d3b8, 'libresource_coordinator_public_mojom.cr.so'),
(0x0c198000, 0x0c2033e8, 0x0006b3e8, 'libresource_coordinator_public_mojom_blink.cr.so'),
(0x0c204000, 0x0c219744, 0x00015744, 'libresource_coordinator_public_mojom_shared.cr.so'),
(0x0c21a000, 0x0c21e700, 0x00004700, 'libsandbox.cr.so'),
(0x0c21f000, 0x0c22f96c, 0x0001096c, 'libsandbox_services.cr.so'),
(0x0c230000, 0x0c249d58, 0x00019d58, 'libseccomp_bpf.cr.so'),
(0x0c24a000, 0x0c24e714, 0x00004714, 'libseccomp_starter_android.cr.so'),
(0x0c24f000, 0x0c4ae9f0, 0x0025f9f0, 'libservice.cr.so'),
(0x0c4af000, 0x0c4c3ae4, 0x00014ae4, 'libservice_manager_cpp.cr.so'),
(0x0c4c4000, 0x0c4cb708, 0x00007708, 'libservice_manager_cpp_types.cr.so'),
(0x0c4cc000, 0x0c4fbe30, 0x0002fe30, 'libservice_manager_mojom.cr.so'),
(0x0c4fc000, 0x0c532e78, 0x00036e78, 'libservice_manager_mojom_blink.cr.so'),
(0x0c533000, 0x0c53669c, 0x0000369c, 'libservice_manager_mojom_constants.cr.so'),
(0x0c537000, 0x0c53e85c, 0x0000785c, 'libservice_manager_mojom_constants_blink.cr.so'),
(0x0c53f000, 0x0c542668, 0x00003668, 'libservice_manager_mojom_constants_shared.cr.so'),
(0x0c543000, 0x0c54d700, 0x0000a700, 'libservice_manager_mojom_shared.cr.so'),
(0x0c54e000, 0x0c8fc6ec, 0x003ae6ec, 'libsessions.cr.so'),
(0x0c8fd000, 0x0c90a924, 0x0000d924, 'libshared_memory_support.cr.so'),
(0x0c90b000, 0x0c9148ec, 0x000098ec, 'libshell_dialogs.cr.so'),
(0x0c915000, 0x0cf8de70, 0x00678e70, 'libskia.cr.so'),
(0x0cf8e000, 0x0cf978bc, 0x000098bc, 'libsnapshot.cr.so'),
(0x0cf98000, 0x0cfb7d9c, 0x0001fd9c, 'libsql.cr.so'),
(0x0cfb8000, 0x0cfbe744, 0x00006744, 'libstartup_tracing.cr.so'),
(0x0cfbf000, 0x0d19b4e4, 0x001dc4e4, 'libstorage_browser.cr.so'),
(0x0d19c000, 0x0d2a773c, 0x0010b73c, 'libstorage_common.cr.so'),
(0x0d2a8000, 0x0d2ac6fc, 0x000046fc, 'libsurface.cr.so'),
(0x0d2ad000, 0x0d2baa98, 0x0000da98, 'libtracing.cr.so'),
(0x0d2bb000, 0x0d2f36b0, 0x000386b0, 'libtracing_cpp.cr.so'),
(0x0d2f4000, 0x0d326e70, 0x00032e70, 'libtracing_mojom.cr.so'),
(0x0d327000, 0x0d33270c, 0x0000b70c, 'libtracing_mojom_shared.cr.so'),
(0x0d333000, 0x0d46d804, 0x0013a804, 'libui_android.cr.so'),
(0x0d46e000, 0x0d4cb3f8, 0x0005d3f8, 'libui_base.cr.so'),
(0x0d4cc000, 0x0d4dbc40, 0x0000fc40, 'libui_base_ime.cr.so'),
(0x0d4dc000, 0x0d4e58d4, 0x000098d4, 'libui_data_pack.cr.so'),
(0x0d4e6000, 0x0d51d1e0, 0x000371e0, 'libui_devtools.cr.so'),
(0x0d51e000, 0x0d52b984, 0x0000d984, 'libui_message_center_cpp.cr.so'),
(0x0d52c000, 0x0d539a48, 0x0000da48, 'libui_touch_selection.cr.so'),
(0x0d53a000, 0x0d55bc60, 0x00021c60, 'liburl.cr.so'),
(0x0d55c000, 0x0d55f6b4, 0x000036b4, 'liburl_ipc.cr.so'),
(0x0d560000, 0x0d5af110, 0x0004f110, 'liburl_matcher.cr.so'),
(0x0d5b0000, 0x0d5e2fac, 0x00032fac, 'libuser_manager.cr.so'),
(0x0d5e3000, 0x0d5e66e4, 0x000036e4, 'libuser_prefs.cr.so'),
(0x0d5e7000, 0x0e3e1cc8, 0x00dfacc8, 'libv8.cr.so'),
(0x0e3e2000, 0x0e400ae0, 0x0001eae0, 'libv8_libbase.cr.so'),
(0x0e401000, 0x0e4d91d4, 0x000d81d4, 'libviz_common.cr.so'),
(0x0e4da000, 0x0e4df7e4, 0x000057e4, 'libviz_resource_format.cr.so'),
(0x0e4e0000, 0x0e5b7120, 0x000d7120, 'libweb_dialogs.cr.so'),
(0x0e5b8000, 0x0e5c7a18, 0x0000fa18, 'libwebdata_common.cr.so'),
(0x0e5c8000, 0x0e61bfe4, 0x00053fe4, 'libwtf.cr.so'),
]
# A small memory map fragment extracted from a tombstone for a process that
# had loaded the APK corresponding to _TEST_APK_LIBS above.
_TEST_MEMORY_MAP = r'''memory map:
12c00000-12ccafff rw- 0 cb000 /dev/ashmem/dalvik-main space (deleted)
12ccb000-130cafff rw- cb000 400000 /dev/ashmem/dalvik-main space (deleted)
130cb000-32bfffff --- 4cb000 1fb35000 /dev/ashmem/dalvik-main space (deleted)
32c00000-32c00fff rw- 0 1000 /dev/ashmem/dalvik-main space 1 (deleted)
32c01000-52bfffff --- 1000 1ffff000 /dev/ashmem/dalvik-main space 1 (deleted)
6f3b8000-6fd90fff rw- 0 9d9000 /data/dalvik-cache/x86/system@framework@boot.art
6fd91000-71c42fff r-- 0 1eb2000 /data/dalvik-cache/x86/system@framework@boot.oat
71c43000-7393efff r-x 1eb2000 1cfc000 /data/dalvik-cache/x86/system@framework@boot.oat (load base 0x71c43000)
7393f000-7393ffff rw- 3bae000 1000 /data/dalvik-cache/x86/system@framework@boot.oat
73940000-73a1bfff rw- 0 dc000 /dev/ashmem/dalvik-zygote space (deleted)
73a1c000-73a1cfff rw- 0 1000 /dev/ashmem/dalvik-non moving space (deleted)
73a1d000-73a2dfff rw- 1000 11000 /dev/ashmem/dalvik-non moving space (deleted)
73a2e000-77540fff --- 12000 3b13000 /dev/ashmem/dalvik-non moving space (deleted)
77541000-7793ffff rw- 3b25000 3ff000 /dev/ashmem/dalvik-non moving space (deleted)
923aa000-92538fff r-- 8a9000 18f000 /data/app/com.example.app-2/base.apk
92539000-9255bfff r-- 0 23000 /data/data/com.example.app/app_data/paks/es.pak@162db1c6689
9255c000-92593fff r-- 213000 38000 /data/app/com.example.app-2/base.apk
92594000-925c0fff r-- 87d000 2d000 /data/app/com.example.app-2/base.apk
925c1000-927d3fff r-- a37000 213000 /data/app/com.example.app-2/base.apk
927d4000-92e07fff r-- 24a000 634000 /data/app/com.example.app-2/base.apk
92e08000-92e37fff r-- a931000 30000 /data/app/com.example.app-2/base.apk
92e38000-92e86fff r-x a961000 4f000 /data/app/com.example.app-2/base.apk
92e87000-92e8afff rw- a9b0000 4000 /data/app/com.example.app-2/base.apk
92e8b000-92e8bfff rw- 0 1000
92e8c000-92e9dfff r-- d5b0000 12000 /data/app/com.example.app-2/base.apk
92e9e000-92ebcfff r-x d5c2000 1f000 /data/app/com.example.app-2/base.apk
92ebd000-92ebefff rw- d5e1000 2000 /data/app/com.example.app-2/base.apk
92ebf000-92ebffff rw- 0 1000
'''
# list of (address, size, path, offset) tuples that must appear in
# _TEST_MEMORY_MAP. Not all sections need to be listed.
_TEST_MEMORY_MAP_SECTIONS = [
(0x923aa000, 0x18f000, '/data/app/com.example.app-2/base.apk', 0x8a9000),
(0x9255c000, 0x038000, '/data/app/com.example.app-2/base.apk', 0x213000),
(0x92594000, 0x02d000, '/data/app/com.example.app-2/base.apk', 0x87d000),
(0x925c1000, 0x213000, '/data/app/com.example.app-2/base.apk', 0xa37000),
]
_EXPECTED_TEST_MEMORY_MAP = r'''memory map:
12c00000-12ccafff rw- 0 cb000 /dev/ashmem/dalvik-main space (deleted)
12ccb000-130cafff rw- cb000 400000 /dev/ashmem/dalvik-main space (deleted)
130cb000-32bfffff --- 4cb000 1fb35000 /dev/ashmem/dalvik-main space (deleted)
32c00000-32c00fff rw- 0 1000 /dev/ashmem/dalvik-main space 1 (deleted)
32c01000-52bfffff --- 1000 1ffff000 /dev/ashmem/dalvik-main space 1 (deleted)
6f3b8000-6fd90fff rw- 0 9d9000 /data/dalvik-cache/x86/system@framework@boot.art
6fd91000-71c42fff r-- 0 1eb2000 /data/dalvik-cache/x86/system@framework@boot.oat
71c43000-7393efff r-x 1eb2000 1cfc000 /data/dalvik-cache/x86/system@framework@boot.oat (load base 0x71c43000)
7393f000-7393ffff rw- 3bae000 1000 /data/dalvik-cache/x86/system@framework@boot.oat
73940000-73a1bfff rw- 0 dc000 /dev/ashmem/dalvik-zygote space (deleted)
73a1c000-73a1cfff rw- 0 1000 /dev/ashmem/dalvik-non moving space (deleted)
73a1d000-73a2dfff rw- 1000 11000 /dev/ashmem/dalvik-non moving space (deleted)
73a2e000-77540fff --- 12000 3b13000 /dev/ashmem/dalvik-non moving space (deleted)
77541000-7793ffff rw- 3b25000 3ff000 /dev/ashmem/dalvik-non moving space (deleted)
923aa000-92538fff r-- 8a9000 18f000 /data/app/com.example.app-2/base.apk
92539000-9255bfff r-- 0 23000 /data/data/com.example.app/app_data/paks/es.pak@162db1c6689
9255c000-92593fff r-- 213000 38000 /data/app/com.example.app-2/base.apk
92594000-925c0fff r-- 87d000 2d000 /data/app/com.example.app-2/base.apk
925c1000-927d3fff r-- a37000 213000 /data/app/com.example.app-2/base.apk
927d4000-92e07fff r-- 24a000 634000 /data/app/com.example.app-2/base.apk
92e08000-92e37fff r-- a931000 30000 /data/app/com.example.app-2/base.apk!lib/libmanager.cr.so (offset 0x0)
92e38000-92e86fff r-x a961000 4f000 /data/app/com.example.app-2/base.apk!lib/libmanager.cr.so (offset 0x30000)
92e87000-92e8afff rw- a9b0000 4000 /data/app/com.example.app-2/base.apk!lib/libmanager.cr.so (offset 0x7f000)
92e8b000-92e8bfff rw- 0 1000
92e8c000-92e9dfff r-- d5b0000 12000 /data/app/com.example.app-2/base.apk!lib/libuser_manager.cr.so (offset 0x0)
92e9e000-92ebcfff r-x d5c2000 1f000 /data/app/com.example.app-2/base.apk!lib/libuser_manager.cr.so (offset 0x12000)
92ebd000-92ebefff rw- d5e1000 2000 /data/app/com.example.app-2/base.apk!lib/libuser_manager.cr.so (offset 0x31000)
92ebf000-92ebffff rw- 0 1000
'''
# Example stack section, taken from the same tombstone that _TEST_MEMORY_MAP
# was extracted from.
_TEST_STACK = r'''stack:
bf89a070 b7439468 /system/lib/libc.so
bf89a074 bf89a1e4 [stack]
bf89a078 932d4000 /data/app/com.example.app-2/base.apk
bf89a07c b73bfbc9 /system/lib/libc.so (pthread_mutex_lock+65)
bf89a080 00000000
bf89a084 4000671c /dev/ashmem/dalvik-main space 1 (deleted)
bf89a088 932d1d86 /data/app/com.example.app-2/base.apk
bf89a08c b743671c /system/lib/libc.so
bf89a090 b77f8c00 /system/bin/linker
bf89a094 b743cc90
bf89a098 932d1d4a /data/app/com.example.app-2/base.apk
bf89a09c b73bf271 /system/lib/libc.so (__pthread_internal_find(long)+65)
bf89a0a0 b743cc90
bf89a0a4 bf89a0b0 [stack]
bf89a0a8 bf89a0b8 [stack]
bf89a0ac 00000008
........ ........
#00 bf89a0b0 00000006
bf89a0b4 00000002
bf89a0b8 b743671c /system/lib/libc.so
bf89a0bc b73bf5d9 /system/lib/libc.so (pthread_kill+71)
#01 bf89a0c0 00006937
bf89a0c4 00006937
bf89a0c8 00000006
bf89a0cc b77fd3a9 /system/bin/app_process32 (sigprocmask+141)
bf89a0d0 00000002
bf89a0d4 bf89a0ec [stack]
bf89a0d8 00000000
bf89a0dc b743671c /system/lib/libc.so
bf89a0e0 bf89a12c [stack]
bf89a0e4 bf89a1e4 [stack]
bf89a0e8 932d1d4a /data/app/com.example.app-2/base.apk
bf89a0ec b7365206 /system/lib/libc.so (raise+37)
#02 bf89a0f0 b77f8c00 /system/bin/linker
bf89a0f4 00000006
bf89a0f8 b7439468 /system/lib/libc.so
bf89a0fc b743671c /system/lib/libc.so
bf89a100 bf89a12c [stack]
bf89a104 b743671c /system/lib/libc.so
bf89a108 bf89a12c [stack]
bf89a10c b735e9e5 /system/lib/libc.so (abort+81)
#03 bf89a110 00000006
bf89a114 bf89a12c [stack]
bf89a118 00000000
bf89a11c b55a3d3b /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::DefaultLogHandler(google::protobuf::LogLevel, char const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)+99)
bf89a120 b7439468 /system/lib/libc.so
bf89a124 b55ba38d /system/lib/libprotobuf-cpp-lite.so
bf89a128 b55ba408 /system/lib/libprotobuf-cpp-lite.so
bf89a12c ffffffdf
bf89a130 0000003d
bf89a134 adfedf00 [anon:libc_malloc]
bf89a138 bf89a158 [stack]
#04 bf89a13c a0cee7f0 /data/app/com.example.app-2/base.apk
bf89a140 b55c1cb0 /system/lib/libprotobuf-cpp-lite.so
bf89a144 bf89a1e4 [stack]
'''
# Expected value of _TEST_STACK after translation of addresses in the APK
# into offsets into libraries.
_EXPECTED_STACK = r'''stack:
bf89a070 b7439468 /system/lib/libc.so
bf89a074 bf89a1e4 [stack]
bf89a078 932d4000 /data/app/com.example.app-2/base.apk
bf89a07c b73bfbc9 /system/lib/libc.so (pthread_mutex_lock+65)
bf89a080 00000000
bf89a084 4000671c /dev/ashmem/dalvik-main space 1 (deleted)
bf89a088 932d1d86 /data/app/com.example.app-2/base.apk
bf89a08c b743671c /system/lib/libc.so
bf89a090 b77f8c00 /system/bin/linker
bf89a094 b743cc90
bf89a098 932d1d4a /data/app/com.example.app-2/base.apk
bf89a09c b73bf271 /system/lib/libc.so (__pthread_internal_find(long)+65)
bf89a0a0 b743cc90
bf89a0a4 bf89a0b0 [stack]
bf89a0a8 bf89a0b8 [stack]
bf89a0ac 00000008
........ ........
#00 bf89a0b0 00000006
bf89a0b4 00000002
bf89a0b8 b743671c /system/lib/libc.so
bf89a0bc b73bf5d9 /system/lib/libc.so (pthread_kill+71)
#01 bf89a0c0 00006937
bf89a0c4 00006937
bf89a0c8 00000006
bf89a0cc b77fd3a9 /system/bin/app_process32 (sigprocmask+141)
bf89a0d0 00000002
bf89a0d4 bf89a0ec [stack]
bf89a0d8 00000000
bf89a0dc b743671c /system/lib/libc.so
bf89a0e0 bf89a12c [stack]
bf89a0e4 bf89a1e4 [stack]
bf89a0e8 932d1d4a /data/app/com.example.app-2/base.apk
bf89a0ec b7365206 /system/lib/libc.so (raise+37)
#02 bf89a0f0 b77f8c00 /system/bin/linker
bf89a0f4 00000006
bf89a0f8 b7439468 /system/lib/libc.so
bf89a0fc b743671c /system/lib/libc.so
bf89a100 bf89a12c [stack]
bf89a104 b743671c /system/lib/libc.so
bf89a108 bf89a12c [stack]
bf89a10c b735e9e5 /system/lib/libc.so (abort+81)
#03 bf89a110 00000006
bf89a114 bf89a12c [stack]
bf89a118 00000000
bf89a11c b55a3d3b /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::DefaultLogHandler(google::protobuf::LogLevel, char const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)+99)
bf89a120 b7439468 /system/lib/libc.so
bf89a124 b55ba38d /system/lib/libprotobuf-cpp-lite.so
bf89a128 b55ba408 /system/lib/libprotobuf-cpp-lite.so
bf89a12c ffffffdf
bf89a130 0000003d
bf89a134 adfedf00 [anon:libc_malloc]
bf89a138 bf89a158 [stack]
#04 bf89a13c a0cee7f0 /data/app/com.example.app-2/base.apk
bf89a140 b55c1cb0 /system/lib/libprotobuf-cpp-lite.so
bf89a144 bf89a1e4 [stack]
'''
_TEST_BACKTRACE = r'''backtrace:
#00 pc 00084126 /system/lib/libc.so (tgkill+22)
#01 pc 000815d8 /system/lib/libc.so (pthread_kill+70)
#02 pc 00027205 /system/lib/libc.so (raise+36)
#03 pc 000209e4 /system/lib/libc.so (abort+80)
#04 pc 0000cf73 /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::LogMessage::Finish()+117)
#05 pc 0000cf8e /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::LogFinisher::operator=(google::protobuf::internal::LogMessage&)+26)
#06 pc 0000d27f /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::VerifyVersion(int, int, char const*)+574)
#07 pc 007cd236 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#08 pc 000111a9 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0xbfc2000)
#09 pc 00013228 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0xbfc2000)
#10 pc 000131de /data/app/com.google.android.apps.chrome-2/base.apk (offset 0xbfc2000)
#11 pc 007cd2d8 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#12 pc 007cd956 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#13 pc 007c2d4a /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#14 pc 009fc9f1 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#15 pc 009fc8ea /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#16 pc 00561c63 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#17 pc 0106fbdb /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#18 pc 004d7371 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#19 pc 004d8159 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#20 pc 004d7b96 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#21 pc 004da4b6 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#22 pc 005ab66c /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
#23 pc 005afca2 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
#24 pc 0000cae8 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
#25 pc 00ce864f /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
#26 pc 00ce8dfa /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
#27 pc 00ce74c6 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
#28 pc 00004616 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x961e000)
#29 pc 00ce8215 /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
#30 pc 0013d8c7 /system/lib/libart.so (art_quick_generic_jni_trampoline+71)
#31 pc 00137c52 /system/lib/libart.so (art_quick_invoke_static_stub+418)
#32 pc 00143651 /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+353)
#33 pc 005e06ae /system/lib/libart.so (artInterpreterToCompiledCodeBridge+190)
#34 pc 00328b5d /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
#35 pc 0032cfc0 /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)0, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+160)
#36 pc 000fc703 /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29891)
#37 pc 00300af7 /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
#38 pc 00328b5d /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
#39 pc 0032cfc0 /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)0, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+160)
#40 pc 000fc703 /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29891)
#41 pc 00300af7 /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
#42 pc 00328b5d /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
#43 pc 0032ebf9 /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)2, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+297)
#44 pc 000fc955 /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+30485)
#45 pc 00300af7 /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
#46 pc 00328b5d /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
#47 pc 0033090c /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)4, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+636)
#48 pc 000fc67f /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29759)
#49 pc 00300700 /system/lib/libart.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*)+128)
#50 pc 00667c73 /system/lib/libart.so (artQuickToInterpreterBridge+808)
#51 pc 0013d98d /system/lib/libart.so (art_quick_to_interpreter_bridge+77)
#52 pc 7264bc5b /data/dalvik-cache/x86/system@framework@boot.oat (offset 0x1eb2000)
'''
_EXPECTED_BACKTRACE = r'''backtrace:
#00 pc 00084126 /system/lib/libc.so (tgkill+22)
#01 pc 000815d8 /system/lib/libc.so (pthread_kill+70)
#02 pc 00027205 /system/lib/libc.so (raise+36)
#03 pc 000209e4 /system/lib/libc.so (abort+80)
#04 pc 0000cf73 /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::LogMessage::Finish()+117)
#05 pc 0000cf8e /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::LogFinisher::operator=(google::protobuf::internal::LogMessage&)+26)
#06 pc 0000d27f /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::VerifyVersion(int, int, char const*)+574)
#07 pc 007cd236 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#08 pc 000111a9 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libprotobuf_lite.cr.so (offset 0x1c000)
#09 pc 00013228 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libprotobuf_lite.cr.so (offset 0x1c000)
#10 pc 000131de /data/app/com.google.android.apps.chrome-2/base.apk!lib/libprotobuf_lite.cr.so (offset 0x1c000)
#11 pc 007cd2d8 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#12 pc 007cd956 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#13 pc 007c2d4a /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#14 pc 009fc9f1 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#15 pc 009fc8ea /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#16 pc 00561c63 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#17 pc 0106fbdb /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#18 pc 004d7371 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#19 pc 004d8159 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#20 pc 004d7b96 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#21 pc 004da4b6 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#22 pc 005ab66c /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
#23 pc 005afca2 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
#24 pc 0000cae8 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
#25 pc 00ce864f /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
#26 pc 00ce8dfa /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
#27 pc 00ce74c6 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
#28 pc 00004616 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libembedder.cr.so (offset 0x28000)
#29 pc 00ce8215 /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
#30 pc 0013d8c7 /system/lib/libart.so (art_quick_generic_jni_trampoline+71)
#31 pc 00137c52 /system/lib/libart.so (art_quick_invoke_static_stub+418)
#32 pc 00143651 /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+353)
#33 pc 005e06ae /system/lib/libart.so (artInterpreterToCompiledCodeBridge+190)
#34 pc 00328b5d /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
#35 pc 0032cfc0 /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)0, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+160)
#36 pc 000fc703 /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29891)
#37 pc 00300af7 /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
#38 pc 00328b5d /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
#39 pc 0032cfc0 /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)0, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+160)
#40 pc 000fc703 /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29891)
#41 pc 00300af7 /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
#42 pc 00328b5d /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
#43 pc 0032ebf9 /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)2, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+297)
#44 pc 000fc955 /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+30485)
#45 pc 00300af7 /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
#46 pc 00328b5d /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
#47 pc 0033090c /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)4, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+636)
#48 pc 000fc67f /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29759)
#49 pc 00300700 /system/lib/libart.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*)+128)
#50 pc 00667c73 /system/lib/libart.so (artQuickToInterpreterBridge+808)
#51 pc 0013d98d /system/lib/libart.so (art_quick_to_interpreter_bridge+77)
#52 pc 7264bc5b /data/dalvik-cache/x86/system@framework@boot.oat (offset 0x1eb2000)
'''
_EXPECTED_BACKTRACE_OFFSETS_MAP = {
'/data/app/com.google.android.apps.chrome-2/base.apk!lib/libprotobuf_lite.cr.so':
set([
0x1c000 + 0x111a9,
0x1c000 + 0x13228,
0x1c000 + 0x131de,
]),
'/data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so':
set([
0x90e000 + 0x7cd236,
0x90e000 + 0x7cd2d8,
0x90e000 + 0x7cd956,
0x90e000 + 0x7c2d4a,
0x90e000 + 0x9fc9f1,
0x90e000 + 0x9fc8ea,
0x90e000 + 0x561c63,
0x90e000 + 0x106fbdb,
0x90e000 + 0x4d7371,
0x90e000 + 0x4d8159,
0x90e000 + 0x4d7b96,
0x90e000 + 0x4da4b6,
0x90e000 + 0xcae8,
]),
'/data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so':
set([
0xc2d000 + 0x5ab66c,
0xc2d000 + 0x5afca2,
0xc2d000 + 0xce864f,
0xc2d000 + 0xce8dfa,
0xc2d000 + 0xce74c6,
0xc2d000 + 0xce8215,
]),
'/data/app/com.google.android.apps.chrome-2/base.apk!lib/libembedder.cr.so':
set([
0x28000 + 0x4616,
])
}
# pylint: enable=line-too-long
_ONE_MB = 1024 * 1024
_TEST_SYMBOL_DATA = {
# Regular symbols
0: 'mock_sym_for_addr_0 [mock_src/libmock1.so.c:0]',
0x1000: 'mock_sym_for_addr_4096 [mock_src/libmock1.so.c:4096]',
# Symbols without source file path.
_ONE_MB: 'mock_sym_for_addr_1048576 [??:0]',
_ONE_MB + 0x8234: 'mock_sym_for_addr_1081908 [??:0]',
# Unknown symbol.
2 * _ONE_MB: '?? [??:0]',
# Inlined symbol.
3 * _ONE_MB:
'mock_sym_for_addr_3145728_inner [mock_src/libmock1.so.c:3145728]',
}
@contextlib.contextmanager
def _TempDir():
dirname = tempfile.mkdtemp()
try:
yield dirname
finally:
shutil.rmtree(dirname)
def _TouchFile(path):
# Create parent directories.
try:
os.makedirs(os.path.dirname(path))
except OSError:
pass
with open(path, 'a'):
os.utime(path, None)
class MockApkTranslator(object):
"""A mock ApkLibraryPathTranslator object used for testing."""
# Regex that matches the content of APK native library map files generated
# with apk_lib_dump.py.
_RE_MAP_FILE = re.compile(
r'0x(?P<file_start>[0-9a-f]+)\s+' +
r'0x(?P<file_end>[0-9a-f]+)\s+' +
r'0x(?P<file_size>[0-9a-f]+)\s+' +
r'0x(?P<lib_path>[0-9a-f]+)\s+')
def __init__(self, test_apk_libs=None):
"""Initialize instance.
Args:
test_apk_libs: Optional list of (file_start, file_end, size, lib_path)
tuples, like _TEST_APK_LIBS for example. This will be used to
implement TranslatePath().
"""
self._apk_libs = []
if test_apk_libs:
self._AddLibEntries(test_apk_libs)
def _AddLibEntries(self, entries):
self._apk_libs = sorted(self._apk_libs + entries,
lambda x, y: cmp(x[0], y[0]))
def ReadMapFile(self, file_path):
"""Read an .apk.native-libs file that was produced with apk_lib_dump.py.
Args:
file_path: input path to .apk.native-libs file. Its format is
essentially: 0x<start> 0x<end> 0x<size> <library-path>
"""
new_libs = []
with open(file_path) as f:
for line in f.readlines():
m = MockApkTranslator._RE_MAP_FILE.match(line)
if m:
file_start = int(m.group('file_start'), 16)
file_end = int(m.group('file_end'), 16)
file_size = int(m.group('file_size'), 16)
lib_path = m.group('lib_path')
# Sanity check
if file_start + file_size != file_end:
logging.warning('%s: Inconsistent (start, end, size) values '
'(0x%x, 0x%x, 0x%x)',
file_path, file_start, file_end, file_size)
else:
new_libs.append((file_start, file_end, file_size, lib_path))
self._AddLibEntries(new_libs)
def TranslatePath(self, lib_path, lib_offset):
"""Translate an APK file path + offset into a library path + offset."""
min_pos = 0
max_pos = len(self._apk_libs)
while min_pos < max_pos:
mid_pos = (min_pos + max_pos) / 2
mid_entry = self._apk_libs[mid_pos]
mid_offset = mid_entry[0]
mid_size = mid_entry[2]
if lib_offset < mid_offset:
max_pos = mid_pos
elif lib_offset >= mid_offset + mid_size:
min_pos = mid_pos + 1
else:
# Found it
new_path = '%s!lib/%s' % (lib_path, mid_entry[3])
new_offset = lib_offset - mid_offset
return (new_path, new_offset)
return lib_path, lib_offset
class HostLibraryFinderTest(unittest.TestCase):
def testEmpty(self):
finder = symbol_utils.HostLibraryFinder()
self.assertIsNone(finder.Find('/data/data/com.example.app-1/lib/libfoo.so'))
self.assertIsNone(
finder.Find('/data/data/com.example.app-1/base.apk!lib/libfoo.so'))
def testSimpleDirectory(self):
finder = symbol_utils.HostLibraryFinder()
with _TempDir() as tmp_dir:
host_libfoo_path = os.path.join(tmp_dir, 'libfoo.so')
host_libbar_path = os.path.join(tmp_dir, 'libbar.so')
_TouchFile(host_libfoo_path)
_TouchFile(host_libbar_path)
finder.AddSearchDir(tmp_dir)
# Regular library path (extracted at installation by the PackageManager).
# Note that the extraction path has changed between Android releases,
# i.e. it can be /data/app/, /data/data/ or /data/app-lib/ depending
# on the system.
self.assertEqual(
host_libfoo_path,
finder.Find('/data/app-lib/com.example.app-1/lib/libfoo.so'))
# Verify that the path doesn't really matter
self.assertEqual(
host_libfoo_path,
finder.Find('/whatever/what.apk!lib/libfoo.so'))
self.assertEqual(
host_libbar_path,
finder.Find('/data/data/com.example.app-1/lib/libbar.so'))
self.assertIsNone(
finder.Find('/data/data/com.example.app-1/lib/libunknown.so'))
def testMultipleDirectories(self):
with _TempDir() as tmp_dir:
# Create the following files:
# <tmp_dir>/aaa/
# libfoo.so
# <tmp_dir>/bbb/
# libbar.so
# libfoo.so (this one should never be seen because 'aaa'
# shall be first in the search path list).
#
aaa_dir = os.path.join(tmp_dir, 'aaa')
bbb_dir = os.path.join(tmp_dir, 'bbb')
os.makedirs(aaa_dir)
os.makedirs(bbb_dir)
host_libfoo_path = os.path.join(aaa_dir, 'libfoo.so')
host_libbar_path = os.path.join(bbb_dir, 'libbar.so')
host_libfoo2_path = os.path.join(bbb_dir, 'libfoo.so')
_TouchFile(host_libfoo_path)
_TouchFile(host_libbar_path)
_TouchFile(host_libfoo2_path)
finder = symbol_utils.HostLibraryFinder()
finder.AddSearchDir(aaa_dir)
finder.AddSearchDir(bbb_dir)
self.assertEqual(
host_libfoo_path,
finder.Find('/data/data/com.example.app-1/lib/libfoo.so'))
self.assertEqual(
host_libfoo_path,
finder.Find('/data/whatever/base.apk!lib/libfoo.so'))
self.assertEqual(
host_libbar_path,
finder.Find('/data/data/com.example.app-1/lib/libbar.so'))
self.assertIsNone(
finder.Find('/data/data/com.example.app-1/lib/libunknown.so'))
class ElfSymbolResolverTest(unittest.TestCase):
def testCreation(self):
resolver = symbol_utils.ElfSymbolResolver(
addr2line_path_for_tests=_MOCK_A2L_PATH)
self.assertTrue(resolver)
def testWithSimpleOffsets(self):
resolver = symbol_utils.ElfSymbolResolver(
addr2line_path_for_tests=_MOCK_A2L_PATH)
resolver.SetAndroidAbi('ignored-abi')
for addr, expected_sym in _TEST_SYMBOL_DATA.iteritems():
self.assertEqual(resolver.FindSymbolInfo('/some/path/libmock1.so', addr),
expected_sym)
def testWithPreResolvedSymbols(self):
resolver = symbol_utils.ElfSymbolResolver(
addr2line_path_for_tests=_MOCK_A2L_PATH)
resolver.SetAndroidAbi('ignored-abi')
resolver.AddLibraryOffsets('/some/path/libmock1.so',
_TEST_SYMBOL_DATA.keys())
resolver.DisallowSymbolizerForTesting()
for addr, expected_sym in _TEST_SYMBOL_DATA.iteritems():
sym_info = resolver.FindSymbolInfo('/some/path/libmock1.so', addr)
self.assertIsNotNone(sym_info, 'None symbol info for addr %x' % addr)
self.assertEqual(
sym_info, expected_sym,
'Invalid symbol info for addr %x [%s] expected [%s]' % (
addr, sym_info, expected_sym))
class MemoryMapTest(unittest.TestCase):
def testCreation(self):
mem_map = symbol_utils.MemoryMap('test-abi32')
self.assertIsNone(mem_map.FindSectionForAddress(0))
def testParseLines(self):
mem_map = symbol_utils.MemoryMap('test-abi32')
mem_map.ParseLines(_TEST_MEMORY_MAP.splitlines())
for exp_addr, exp_size, exp_path, exp_offset in _TEST_MEMORY_MAP_SECTIONS:
text = '(addr:%x, size:%x, path:%s, offset=%x)' % (
exp_addr, exp_size, exp_path, exp_offset)
t = mem_map.FindSectionForAddress(exp_addr)
self.assertTrue(t, 'Could not find %s' % text)
self.assertEqual(t.address, exp_addr)
self.assertEqual(t.size, exp_size)
self.assertEqual(t.offset, exp_offset)
self.assertEqual(t.path, exp_path)
def testTranslateLine(self):
android_abi = 'test-abi'
apk_translator = MockApkTranslator(_TEST_APK_LIBS)
mem_map = symbol_utils.MemoryMap(android_abi)
for line, expected_line in zip(_TEST_MEMORY_MAP.splitlines(),
_EXPECTED_TEST_MEMORY_MAP.splitlines()):
self.assertEqual(mem_map.TranslateLine(line, apk_translator),
expected_line)
class StackTranslatorTest(unittest.TestCase):
def testSimpleStack(self):
android_abi = 'test-abi32'
mem_map = symbol_utils.MemoryMap(android_abi)
mem_map.ParseLines(_TEST_MEMORY_MAP)
apk_translator = MockApkTranslator(_TEST_APK_LIBS)
stack_translator = symbol_utils.StackTranslator(android_abi, mem_map,
apk_translator)
input_stack = _TEST_STACK.splitlines()
expected_stack = _EXPECTED_STACK.splitlines()
self.assertEqual(len(input_stack), len(expected_stack))
for stack_line, expected_line in zip(input_stack, expected_stack):
new_line = stack_translator.TranslateLine(stack_line)
self.assertEqual(new_line, expected_line)
class MockSymbolResolver(symbol_utils.SymbolResolver):
# A regex matching a symbol definition as it appears in a test symbol file.
# Format is: <hex-offset> <whitespace> <symbol-string>
_RE_SYMBOL_DEFINITION = re.compile(
r'(?P<offset>[0-9a-f]+)\s+(?P<symbol>.*)')
def __init__(self):
super(MockSymbolResolver, self).__init__()
self._map = collections.defaultdict(dict)
def AddTestLibrarySymbols(self, lib_name, offsets_map):
"""Add a new test entry for a given library name.
Args:
lib_name: Library name (e.g. 'libfoo.so')
offsets_map: A mapping from offsets to symbol info strings.
"""
self._map[lib_name] = offsets_map
def ReadTestFile(self, file_path, lib_name):
"""Read a single test symbol file, matching a given library.
Args:
file_path: Input file path.
lib_name: Library name these symbols correspond to (e.g. 'libfoo.so')
"""
with open(file_path) as f:
for line in f.readlines():
line = line.rstrip()
m = MockSymbolResolver._RE_SYMBOL_DEFINITION.match(line)
if m:
offset = int(m.group('offset'))
symbol = m.group('symbol')
self._map[lib_name][offset] = symbol
def ReadTestFilesInDir(self, dir_path, file_suffix):
"""Read all symbol test files in a given directory.
Args:
dir_path: Directory path.
file_suffix: File suffix used to detect test symbol files.
"""
for filename in os.listdir(dir_path):
if filename.endswith(file_suffix):
lib_name = filename[:-len(file_suffix)]
self.ReadTestFile(os.path.join(dir_path, filename), lib_name)
def FindSymbolInfo(self, device_path, device_offset):
"""Implement SymbolResolver.FindSymbolInfo."""
lib_name = os.path.basename(device_path)
offsets = self._map.get(lib_name)
if not offsets:
return None
return offsets.get(device_offset)
class BacktraceTranslatorTest(unittest.TestCase):
def testEmpty(self):
android_abi = 'test-abi'
apk_translator = MockApkTranslator()
backtrace_translator = symbol_utils.BacktraceTranslator(android_abi,
apk_translator)
self.assertTrue(backtrace_translator)
def testFindLibraryOffsets(self):
android_abi = 'test-abi'
apk_translator = MockApkTranslator(_TEST_APK_LIBS)
backtrace_translator = symbol_utils.BacktraceTranslator(android_abi,
apk_translator)
input_backtrace = _EXPECTED_BACKTRACE.splitlines()
expected_lib_offsets_map = _EXPECTED_BACKTRACE_OFFSETS_MAP
offset_map = backtrace_translator.FindLibraryOffsets(input_backtrace)
for lib_path, offsets in offset_map.iteritems():
self.assertTrue(lib_path in expected_lib_offsets_map,
'%s is not in expected library-offsets map!' % lib_path)
sorted_offsets = sorted(offsets)
sorted_expected_offsets = sorted(expected_lib_offsets_map[lib_path])
self.assertEqual(sorted_offsets, sorted_expected_offsets,
'%s has invalid offsets %s expected %s' % (
lib_path, sorted_offsets, sorted_expected_offsets))
def testTranslateLine(self):
android_abi = 'test-abi'
apk_translator = MockApkTranslator(_TEST_APK_LIBS)
backtrace_translator = symbol_utils.BacktraceTranslator(android_abi,
apk_translator)
input_backtrace = _TEST_BACKTRACE.splitlines()
expected_backtrace = _EXPECTED_BACKTRACE.splitlines()
self.assertEqual(len(input_backtrace), len(expected_backtrace))
for trace_line, expected_line in zip(input_backtrace, expected_backtrace):
line = backtrace_translator.TranslateLine(trace_line,
MockSymbolResolver())
self.assertEqual(line, expected_line)
if __name__ == '__main__':
unittest.main()