// 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. #ifndef FLUTTER_FML_MAPPING_H_ #define FLUTTER_FML_MAPPING_H_ #include #include #include #include #include "flutter/fml/build_config.h" #include "flutter/fml/file.h" #include "flutter/fml/macros.h" #include "flutter/fml/native_library.h" #include "flutter/fml/unique_fd.h" namespace fml { class Mapping { public: Mapping(); virtual ~Mapping(); virtual size_t GetSize() const = 0; virtual const uint8_t* GetMapping() const = 0; // Whether calling madvise(DONTNEED) on the mapping is non-destructive. // Generally true for file-mapped memory and false for anonymous memory. virtual bool IsDontNeedSafe() const = 0; private: FML_DISALLOW_COPY_AND_ASSIGN(Mapping); }; class FileMapping final : public Mapping { public: enum class Protection { kRead, kWrite, kExecute, }; explicit FileMapping(const fml::UniqueFD& fd, std::initializer_list protection = { Protection::kRead}); ~FileMapping() override; static std::unique_ptr CreateReadOnly(const std::string& path); static std::unique_ptr CreateReadOnly( const fml::UniqueFD& base_fd, const std::string& sub_path = ""); static std::unique_ptr CreateReadExecute( const std::string& path); static std::unique_ptr CreateReadExecute( const fml::UniqueFD& base_fd, const std::string& sub_path = ""); // |Mapping| size_t GetSize() const override; // |Mapping| const uint8_t* GetMapping() const override; // |Mapping| bool IsDontNeedSafe() const override; uint8_t* GetMutableMapping(); bool IsValid() const; private: bool valid_ = false; size_t size_ = 0; uint8_t* mapping_ = nullptr; uint8_t* mutable_mapping_ = nullptr; #if FML_OS_WIN fml::UniqueFD mapping_handle_; #endif FML_DISALLOW_COPY_AND_ASSIGN(FileMapping); }; class DataMapping final : public Mapping { public: explicit DataMapping(std::vector data); explicit DataMapping(const std::string& string); ~DataMapping() override; // |Mapping| size_t GetSize() const override; // |Mapping| const uint8_t* GetMapping() const override; // |Mapping| bool IsDontNeedSafe() const override; private: std::vector data_; FML_DISALLOW_COPY_AND_ASSIGN(DataMapping); }; class NonOwnedMapping final : public Mapping { public: using ReleaseProc = std::function; NonOwnedMapping(const uint8_t* data, size_t size, const ReleaseProc& release_proc = nullptr, bool dontneed_safe = false); ~NonOwnedMapping() override; // |Mapping| size_t GetSize() const override; // |Mapping| const uint8_t* GetMapping() const override; // |Mapping| bool IsDontNeedSafe() const override; private: const uint8_t* const data_; const size_t size_; const ReleaseProc release_proc_; const bool dontneed_safe_; FML_DISALLOW_COPY_AND_ASSIGN(NonOwnedMapping); }; /// A Mapping like NonOwnedMapping, but uses Free as its release proc. class MallocMapping final : public Mapping { public: MallocMapping(); /// Creates a MallocMapping for a region of memory (without copying it). /// The function will `abort()` if the malloc fails. /// @param data The starting address of the mapping. /// @param size The size of the mapping in bytes. MallocMapping(uint8_t* data, size_t size); MallocMapping(fml::MallocMapping&& mapping); ~MallocMapping() override; /// Copies the data from `begin` to `end`. /// It's templated since void* arithemetic isn't allowed and we want support /// for `uint8_t` and `char`. template static MallocMapping Copy(const T* begin, const T* end) { FML_DCHECK(end >= begin); size_t length = end - begin; return Copy(begin, length); } /// Copies a region of memory into a MallocMapping. /// The function will `abort()` if the malloc fails. /// @param begin The starting address of where we will copy. /// @param length The length of the region to copy in bytes. static MallocMapping Copy(const void* begin, size_t length); // |Mapping| size_t GetSize() const override; // |Mapping| const uint8_t* GetMapping() const override; // |Mapping| bool IsDontNeedSafe() const override; /// Removes ownership of the data buffer. /// After this is called; the mapping will point to nullptr. [[nodiscard]] uint8_t* Release(); private: uint8_t* data_; size_t size_; FML_DISALLOW_COPY_AND_ASSIGN(MallocMapping); }; class SymbolMapping final : public Mapping { public: SymbolMapping(fml::RefPtr native_library, const char* symbol_name); ~SymbolMapping() override; // |Mapping| size_t GetSize() const override; // |Mapping| const uint8_t* GetMapping() const override; // |Mapping| bool IsDontNeedSafe() const override; private: fml::RefPtr native_library_; const uint8_t* mapping_ = nullptr; FML_DISALLOW_COPY_AND_ASSIGN(SymbolMapping); }; } // namespace fml #endif // FLUTTER_FML_MAPPING_H_