| // Copyright 2013 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "flutter/fml/mapping.h" | |
| #include <algorithm> | |
| #include <cstring> | |
| #include <memory> | |
| #include <sstream> | |
| namespace fml { | |
| // FileMapping | |
| uint8_t* FileMapping::GetMutableMapping() { | |
| return mutable_mapping_; | |
| } | |
| std::unique_ptr<FileMapping> FileMapping::CreateReadOnly( | |
| const std::string& path) { | |
| return CreateReadOnly(OpenFile(path.c_str(), false, FilePermission::kRead), | |
| ""); | |
| } | |
| std::unique_ptr<FileMapping> FileMapping::CreateReadOnly( | |
| const fml::UniqueFD& base_fd, | |
| const std::string& sub_path) { | |
| if (!sub_path.empty()) { | |
| return CreateReadOnly( | |
| OpenFile(base_fd, sub_path.c_str(), false, FilePermission::kRead), ""); | |
| } | |
| auto mapping = std::make_unique<FileMapping>( | |
| base_fd, std::initializer_list<Protection>{Protection::kRead}); | |
| if (!mapping->IsValid()) { | |
| return nullptr; | |
| } | |
| return mapping; | |
| } | |
| std::unique_ptr<FileMapping> FileMapping::CreateReadExecute( | |
| const std::string& path) { | |
| return CreateReadExecute( | |
| OpenFile(path.c_str(), false, FilePermission::kRead)); | |
| } | |
| std::unique_ptr<FileMapping> FileMapping::CreateReadExecute( | |
| const fml::UniqueFD& base_fd, | |
| const std::string& sub_path) { | |
| if (!sub_path.empty()) { | |
| return CreateReadExecute( | |
| OpenFile(base_fd, sub_path.c_str(), false, FilePermission::kRead), ""); | |
| } | |
| auto mapping = std::make_unique<FileMapping>( | |
| base_fd, std::initializer_list<Protection>{Protection::kRead, | |
| Protection::kExecute}); | |
| if (!mapping->IsValid()) { | |
| return nullptr; | |
| } | |
| return mapping; | |
| } | |
| // Data Mapping | |
| DataMapping::DataMapping(std::vector<uint8_t> data) : data_(std::move(data)) {} | |
| DataMapping::DataMapping(const std::string& string) | |
| : data_(string.begin(), string.end()) {} | |
| DataMapping::~DataMapping() = default; | |
| size_t DataMapping::GetSize() const { | |
| return data_.size(); | |
| } | |
| const uint8_t* DataMapping::GetMapping() const { | |
| return data_.data(); | |
| } | |
| bool DataMapping::IsDontNeedSafe() const { | |
| return false; | |
| } | |
| // NonOwnedMapping | |
| NonOwnedMapping::NonOwnedMapping(const uint8_t* data, | |
| size_t size, | |
| const ReleaseProc& release_proc, | |
| bool dontneed_safe) | |
| : data_(data), | |
| size_(size), | |
| release_proc_(release_proc), | |
| dontneed_safe_(dontneed_safe) {} | |
| NonOwnedMapping::~NonOwnedMapping() { | |
| if (release_proc_) { | |
| release_proc_(data_, size_); | |
| } | |
| } | |
| size_t NonOwnedMapping::GetSize() const { | |
| return size_; | |
| } | |
| const uint8_t* NonOwnedMapping::GetMapping() const { | |
| return data_; | |
| } | |
| bool NonOwnedMapping::IsDontNeedSafe() const { | |
| return dontneed_safe_; | |
| } | |
| // MallocMapping | |
| MallocMapping::MallocMapping() : data_(nullptr), size_(0) {} | |
| MallocMapping::MallocMapping(uint8_t* data, size_t size) | |
| : data_(data), size_(size) {} | |
| MallocMapping::MallocMapping(fml::MallocMapping&& mapping) | |
| : data_(mapping.data_), size_(mapping.size_) { | |
| mapping.data_ = nullptr; | |
| mapping.size_ = 0; | |
| } | |
| MallocMapping::~MallocMapping() { | |
| free(data_); | |
| data_ = nullptr; | |
| } | |
| MallocMapping MallocMapping::Copy(const void* begin, size_t length) { | |
| auto result = | |
| MallocMapping(reinterpret_cast<uint8_t*>(malloc(length)), length); | |
| FML_CHECK(result.GetMapping() != nullptr); | |
| memcpy(const_cast<uint8_t*>(result.GetMapping()), begin, length); | |
| return result; | |
| } | |
| size_t MallocMapping::GetSize() const { | |
| return size_; | |
| } | |
| const uint8_t* MallocMapping::GetMapping() const { | |
| return data_; | |
| } | |
| bool MallocMapping::IsDontNeedSafe() const { | |
| return false; | |
| } | |
| uint8_t* MallocMapping::Release() { | |
| uint8_t* result = data_; | |
| data_ = nullptr; | |
| size_ = 0; | |
| return result; | |
| } | |
| // Symbol Mapping | |
| SymbolMapping::SymbolMapping(fml::RefPtr<fml::NativeLibrary> native_library, | |
| const char* symbol_name) | |
| : native_library_(std::move(native_library)) { | |
| if (native_library_ && symbol_name != nullptr) { | |
| mapping_ = native_library_->ResolveSymbol(symbol_name); | |
| if (mapping_ == nullptr) { | |
| // Apparently, dart_bootstrap seems to account for the Mac behavior of | |
| // requiring the underscore prefixed symbol name on non-Mac platforms as | |
| // well. As a fallback, check the underscore prefixed variant of the | |
| // symbol name and allow callers to not have handle this on a per platform | |
| // toolchain quirk basis. | |
| std::stringstream underscore_symbol_name; | |
| underscore_symbol_name << "_" << symbol_name; | |
| mapping_ = | |
| native_library_->ResolveSymbol(underscore_symbol_name.str().c_str()); | |
| } | |
| } | |
| } | |
| SymbolMapping::~SymbolMapping() = default; | |
| size_t SymbolMapping::GetSize() const { | |
| return 0; | |
| } | |
| const uint8_t* SymbolMapping::GetMapping() const { | |
| return mapping_; | |
| } | |
| bool SymbolMapping::IsDontNeedSafe() const { | |
| return true; | |
| } | |
| } // namespace fml |