Avoid dynamic lookups of the engine library's symbols on Android (flutter/engine#11001)

The dynamic linker on some older versions of Android on x86 fails when doing
dlsym(RTLD_DEFAULT) lookups of symbols exported by the engine library itself.
The engine needs to do this for some data files that are linked into the engine
library (ICU data and Dart snapshot blobs).

To work around this, the engine will declare static symbols for these data
objects on the affected platforms.

Fixes https://github.com/flutter/flutter/issues/20091
This commit is contained in:
Jason Simmons
2019-08-14 12:40:40 -07:00
committed by GitHub
parent 180d5a8530
commit cf6fbe1fdc
2 changed files with 41 additions and 12 deletions

View File

@@ -20,6 +20,14 @@ const char* DartSnapshot::kIsolateDataSymbol = "kDartIsolateSnapshotData";
const char* DartSnapshot::kIsolateInstructionsSymbol =
"kDartIsolateSnapshotInstructions";
// On Windows and Android (in debug mode) the engine finds the Dart snapshot
// data through symbols that are statically linked into the executable.
// On other platforms this data is obtained by a dynamic symbol lookup.
#define DART_SNAPSHOT_STATIC_LINK \
(OS_WIN || (OS_ANDROID && FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG))
#if !DART_SNAPSHOT_STATIC_LINK
static std::unique_ptr<const fml::Mapping> GetFileMapping(
const std::string& path,
bool executable) {
@@ -83,11 +91,13 @@ static std::shared_ptr<const fml::Mapping> SearchMapping(
return nullptr;
}
#endif // !DART_SNAPSHOT_STATIC_LINK
static std::shared_ptr<const fml::Mapping> ResolveVMData(
const Settings& settings) {
#if OS_WIN
#if DART_SNAPSHOT_STATIC_LINK
return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotData, 0);
#else // OS_WIN
#else // DART_SNAPSHOT_STATIC_LINK
return SearchMapping(
settings.vm_snapshot_data, // embedder_mapping_callback
settings.vm_snapshot_data_path, // file_path
@@ -95,14 +105,14 @@ static std::shared_ptr<const fml::Mapping> ResolveVMData(
DartSnapshot::kVMDataSymbol, // native_library_symbol_name
false // is_executable
);
#endif // OS_WIN
#endif // DART_SNAPSHOT_STATIC_LINK
}
static std::shared_ptr<const fml::Mapping> ResolveVMInstructions(
const Settings& settings) {
#if OS_WIN
#if DART_SNAPSHOT_STATIC_LINK
return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotInstructions, 0);
#else // OS_WIN
#else // DART_SNAPSHOT_STATIC_LINK
return SearchMapping(
settings.vm_snapshot_instr, // embedder_mapping_callback
settings.vm_snapshot_instr_path, // file_path
@@ -110,14 +120,14 @@ static std::shared_ptr<const fml::Mapping> ResolveVMInstructions(
DartSnapshot::kVMInstructionsSymbol, // native_library_symbol_name
true // is_executable
);
#endif // OS_WIN
#endif // DART_SNAPSHOT_STATIC_LINK
}
static std::shared_ptr<const fml::Mapping> ResolveIsolateData(
const Settings& settings) {
#if OS_WIN
#if DART_SNAPSHOT_STATIC_LINK
return std::make_unique<fml::NonOwnedMapping>(kDartIsolateSnapshotData, 0);
#else // OS_WIN
#else // DART_SNAPSHOT_STATIC_LINK
return SearchMapping(
settings.isolate_snapshot_data, // embedder_mapping_callback
settings.isolate_snapshot_data_path, // file_path
@@ -125,15 +135,15 @@ static std::shared_ptr<const fml::Mapping> ResolveIsolateData(
DartSnapshot::kIsolateDataSymbol, // native_library_symbol_name
false // is_executable
);
#endif // OS_WIN
#endif // DART_SNAPSHOT_STATIC_LINK
}
static std::shared_ptr<const fml::Mapping> ResolveIsolateInstructions(
const Settings& settings) {
#if OS_WIN
#if DART_SNAPSHOT_STATIC_LINK
return std::make_unique<fml::NonOwnedMapping>(
kDartIsolateSnapshotInstructions, 0);
#else // OS_WIN
#else // DART_SNAPSHOT_STATIC_LINK
return SearchMapping(
settings.isolate_snapshot_instr, // embedder_mapping_callback
settings.isolate_snapshot_instr_path, // file_path
@@ -141,7 +151,7 @@ static std::shared_ptr<const fml::Mapping> ResolveIsolateInstructions(
DartSnapshot::kIsolateInstructionsSymbol, // native_library_symbol_name
true // is_executable
);
#endif // OS_WIN
#endif // DART_SNAPSHOT_STATIC_LINK
}
fml::RefPtr<DartSnapshot> DartSnapshot::VMSnapshotFromSettings(

View File

@@ -53,6 +53,20 @@ static const std::string gDartFlagsWhitelist[] = {
// Include again for struct definition.
#include "flutter/shell/common/switches.h"
// Define symbols for the ICU data that is linked into the Flutter library on
// Android. This is a workaround for crashes seen when doing dynamic lookups
// of the engine's own symbols on some older versions of Android.
#if OS_ANDROID
extern uint8_t _binary_icudtl_dat_start[];
extern uint8_t _binary_icudtl_dat_end[];
static std::unique_ptr<fml::Mapping> GetICUStaticMapping() {
return std::make_unique<fml::NonOwnedMapping>(
_binary_icudtl_dat_start,
_binary_icudtl_dat_end - _binary_icudtl_dat_start);
}
#endif
namespace flutter {
void PrintUsage(const std::string& executable_name) {
@@ -298,9 +312,14 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) {
&icu_symbol_prefix);
command_line.GetOptionValue(FlagForSwitch(Switch::ICUNativeLibPath),
&native_lib_path);
#if OS_ANDROID
settings.icu_mapper = GetICUStaticMapping;
#else
settings.icu_mapper = [icu_symbol_prefix, native_lib_path] {
return GetSymbolMapping(icu_symbol_prefix, native_lib_path);
};
#endif
}
}